Imported Upstream version 1.7.0 upstream/1.7.0
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 18 Jan 2022 02:15:03 +0000 (11:15 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 18 Jan 2022 02:15:03 +0000 (11:15 +0900)
97 files changed:
NEWS
README
configure
configure.ac
ltmain.sh
m4/libtool.m4
src/bin/fstdifference-main.cc
src/extensions/compact/Makefile.am
src/extensions/compact/Makefile.in
src/extensions/compact/compact16_acceptor-fst.cc
src/extensions/compact/compact16_string-fst.cc
src/extensions/compact/compact16_unweighted-fst.cc
src/extensions/compact/compact16_unweighted_acceptor-fst.cc
src/extensions/compact/compact16_weighted_string-fst.cc
src/extensions/compact/compact64_acceptor-fst.cc
src/extensions/compact/compact64_string-fst.cc
src/extensions/compact/compact64_unweighted-fst.cc
src/extensions/compact/compact64_unweighted_acceptor-fst.cc
src/extensions/compact/compact64_weighted_string-fst.cc
src/extensions/compact/compact8_acceptor-fst.cc
src/extensions/compact/compact8_string-fst.cc
src/extensions/compact/compact8_unweighted-fst.cc
src/extensions/compact/compact8_unweighted_acceptor-fst.cc
src/extensions/compact/compact8_weighted_string-fst.cc
src/extensions/compress/Makefile.am
src/extensions/compress/Makefile.in
src/extensions/const/Makefile.am
src/extensions/const/Makefile.in
src/extensions/far/Makefile.am
src/extensions/far/Makefile.in
src/extensions/far/far-class.cc
src/extensions/linear/Makefile.am
src/extensions/linear/Makefile.in
src/extensions/lookahead/Makefile.am
src/extensions/lookahead/Makefile.in
src/extensions/mpdt/Makefile.am
src/extensions/mpdt/Makefile.in
src/extensions/ngram/Makefile.am
src/extensions/ngram/Makefile.in
src/extensions/pdt/Makefile.am
src/extensions/pdt/Makefile.in
src/extensions/python/fst.pxd
src/extensions/python/pywrapfst.cc
src/extensions/python/pywrapfst.pxd
src/extensions/python/pywrapfst.pyx
src/extensions/special/Makefile.am
src/extensions/special/Makefile.in
src/include/fst/arc-map.h
src/include/fst/arc.h
src/include/fst/arcsort.h
src/include/fst/bi-table.h
src/include/fst/cache.h
src/include/fst/compact-fst.h
src/include/fst/compose.h
src/include/fst/connect.h
src/include/fst/const-fst.h
src/include/fst/determinize.h
src/include/fst/equal.h
src/include/fst/expanded-fst.h
src/include/fst/expectation-weight.h
src/include/fst/extensions/far/far-class.h
src/include/fst/factor-weight.h
src/include/fst/float-weight.h
src/include/fst/fst.h
src/include/fst/label-reachable.h
src/include/fst/mapped-file.h
src/include/fst/matcher.h
src/include/fst/minimize.h
src/include/fst/mutable-fst.h
src/include/fst/pair-weight.h
src/include/fst/project.h
src/include/fst/queue.h
src/include/fst/randgen.h
src/include/fst/rational.h
src/include/fst/relabel.h
src/include/fst/replace-util.h
src/include/fst/replace.h
src/include/fst/rmepsilon.h
src/include/fst/shortest-distance.h
src/include/fst/shortest-path.h
src/include/fst/signed-log-weight.h
src/include/fst/sparse-tuple-weight.h
src/include/fst/string.h
src/include/fst/symbol-table.h
src/include/fst/synchronize.h
src/include/fst/tuple-weight.h
src/include/fst/union.h
src/include/fst/util.h
src/include/fst/vector-fst.h
src/lib/Makefile.am
src/lib/Makefile.in
src/lib/fst-types.cc
src/lib/mapped-file.cc
src/lib/symbol-table.cc
src/script/Makefile.am
src/script/Makefile.in
src/test/weight_test.cc

diff --git a/NEWS b/NEWS
index 8147ae3..77a6d03 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,80 +1,88 @@
+OpenFst: Release 1.7
+   * Adds configure-time test for float equality reflexivity (1.7.0)
+   * Adds additional overloads to Equals (1.7.0)
+   * Removes volatile qualifiers from float weights (1.7.0)
+   * Improved use of move semantics, especially in cache-backed FSTs (1.7.0)
+   * Protections for signedness in string compiler (1.7.0)
+   * Clean-up to weight constructors (1.7.0)
+
 OpenFst: Release 1.6
-    * Optimized label lookup in SymbolTable (1.6.9)
-    * Fixed PROGRAM_FLAGS documentation string in binaries (1.6.8)
-    * Fixed handling of symbol tables in EpsNormalize (1.6.8)
-    * Fixed HashMatcher issues with SetState() and Find() consistency (1.6.8)
-    * Fixed error reporting when FST arc type unknown (1.6.8)
-    * The `first_path` option to ShortestPath is now optimal for A* (1.6.7)
-    * Renames SymbolTable::kNoSymbol to kNoSymbol (1.6.7)
-    * Exposes PowerMapper to the scripting API (1.6.7)
-    * Fixes linking of the special SOs (1.6.7)
-    * Fixes error handling in HashMatcher (1.6.6)
-    * Adds kShortestDelta for operations dependent on shortest-distance (1.6.6)
-    * Adds Python methods for (un)pickling and (de)serializing FSTs (1.6.6)
-    * Adds constructive variants of Invert and Project (1.6.6)
-    * Increases code sharing in MemoryPool/MemoryArena (1.6.6)
-    * Improves consistency of matcher FST ownership (1.6.6)
-    * Adds non-trivial A* estimator class (1.6.6)
-    * Prevents unreachable code generation in libfstscript (1.6.5)
-    * Adds move constructors for non-trivial weight types (1.6.5)
-    * Standardizes method names for tuple weight types (1.6.5)
-    * Eliminates undefined behavior in weight hashing (1.6.5)
-    * Optimizes binary search in SortedMatcher (1.6.5)
-    * Adds SetWeight (1.6.5)
-    * Fixes typing error in Python FAR reader (1.6.4)
-    * Removes restriction that Prune argument have commutative weights (1.6.3)
-    * Improves configuration of CompositeWeight readers and writers (1.6.3)
-    * Improves accuracy of ShortestDistance summation (1.6.3)
-    * SetFinal now "moves" its weight argument (1.6.3)
-    * Exposes ArcIterator and EncodeMapper flags in Python (1.6.3)
-    * Properly sets return codes in FST binaries (1.6.3)
-    * Eliminates StringWeight macros (1.6.3)
-    * Finalizes most virtual method overrides (1.6.2)
-    * Fixes missing includes of <fst/log.h> (1.6.1)
-    * Adds float format support to FST drawing (1.6.1)
-    * Extensive modernization for C++11 style (1.6.0)
-    * Many classes and constants moved into an internal namespace (1.6.0)
-    * Adds HashMatcher (1.6.0)
-    * Adds Member method to SymbolTable (1.6.0)
-    * Adds the "special" extension and the fstspecial binary; this is similar to
-      fstconvert but accepts arguments for specifying special labels (phi, rho,
-      and sigma) of FSTs (1.6.0)
-    * Exposes allow_negative_label option for Python symbol tables (1.6.0)
+   * Optimized label lookup in SymbolTable (1.6.9)
+   * Fixed PROGRAM_FLAGS documentation string in binaries (1.6.8)
+   * Fixed handling of symbol tables in EpsNormalize (1.6.8)
+   * Fixed HashMatcher issues with SetState() and Find() consistency (1.6.8)
+   * Fixed error reporting when FST arc type unknown (1.6.8)
+   * The `first_path` option to ShortestPath is now optimal for A* (1.6.7)
+   * Renames SymbolTable::kNoSymbol to kNoSymbol (1.6.7)
+   * Exposes PowerMapper to the scripting API (1.6.7)
+   * Fixes linking of the special SOs (1.6.7)
+   * Fixes error handling in HashMatcher (1.6.6)
+   * Adds kShortestDelta for operations dependent on shortest-distance (1.6.6)
+   * Adds Python methods for (un)pickling and (de)serializing FSTs (1.6.6)
+   * Adds constructive variants of Invert and Project (1.6.6)
+   * Increases code sharing in MemoryPool/MemoryArena (1.6.6)
+   * Improves consistency of matcher FST ownership (1.6.6)
+   * Adds non-trivial A* estimator class (1.6.6)
+   * Prevents unreachable code generation in libfstscript (1.6.5)
+   * Adds move constructors for non-trivial weight types (1.6.5)
+   * Standardizes method names for tuple weight types (1.6.5)
+   * Eliminates undefined behavior in weight hashing (1.6.5)
+   * Optimizes binary search in SortedMatcher (1.6.5)
+   * Adds SetWeight (1.6.5)
+   * Fixes typing error in Python FAR reader (1.6.4)
+   * Removes restriction that Prune argument have commutative weights (1.6.3)
+   * Improves configuration of CompositeWeight readers and writers (1.6.3)
+   * Improves accuracy of ShortestDistance summation (1.6.3)
+   * SetFinal now "moves" its weight argument (1.6.3)
+   * Exposes ArcIterator and EncodeMapper flags in Python (1.6.3)
+   * Properly sets return codes in FST binaries (1.6.3)
+   * Eliminates StringWeight macros (1.6.3)
+   * Finalizes most virtual method overrides (1.6.2)
+   * Fixes missing includes of <fst/log.h> (1.6.1)
+   * Adds float format support to FST drawing (1.6.1)
+   * Extensive modernization for C++11 style (1.6.0)
+   * Many classes and constants moved into an internal namespace (1.6.0)
+   * Adds HashMatcher (1.6.0)
+   * Adds Member method to SymbolTable (1.6.0)
+   * Adds the "special" extension and the fstspecial binary; this is similar to
+     fstconvert but accepts arguments for specifying special labels (phi, rho,
+     and sigma) of FSTs (1.6.0)
+   * Exposes allow_negative_label option for Python symbol tables (1.6.0)
 
 OpenFst: Release 1.5
-    * Added p-subsequential determinization (1.5.0)
-    * Generalized epsilon normalization to non-functional case (1.5.0)
-    * Added general gallic (plus is union) semiring (1.5.0)
-    * Added FST compression extension (1.5.0)
-    * Added Python extension (1.5.0)
-    * Added multiple pushdown transducer (MPDT) support (1.5.0)
-    * Fixed Isomorphic function (1.5.0)
-    * Added final method to matchers (1.5.0)
-    * Fixed various compiler issues (1.5.0)
-    * Fixed missing Isomorphic components (1.5.0)
-    * Added UnionWeight (1.5.0)
-    * Added InputEpsilonMapper and OutputEpsilonMapper arc mappers (1.5.1)
-    * Added TrivialComposeFilter for more efficient composition when one
-      of the arguments is epsilon-free (1.5.1)
-    * Added properties bits kUnweightedCycles and kWeightedCycles (1.5.1)
-    * Added missing const qualification to (1.5.1):
+   * Added p-subsequential determinization (1.5.0)
+   * Generalized epsilon normalization to non-functional case (1.5.0)
+   * Added general gallic (plus is union) semiring (1.5.0)
+   * Added FST compression extension (1.5.0)
+   * Added Python extension (1.5.0)
+   * Added multiple pushdown transducer (MPDT) support (1.5.0)
+   * Fixed Isomorphic function (1.5.0)
+   * Added final method to matchers (1.5.0)
+   * Fixed various compiler issues (1.5.0)
+   * Fixed missing Isomorphic components (1.5.0)
+   * Added UnionWeight (1.5.0)
+   * Added InputEpsilonMapper and OutputEpsilonMapper arc mappers (1.5.1)
+   * Added TrivialComposeFilter for more efficient composition when one
+     of the arguments is epsilon-free (1.5.1)
+   * Added properties bits kUnweightedCycles and kWeightedCycles (1.5.1)
+   * Added missing const qualification to (1.5.1):
       - SymbolTableIterator access
       - EncodeMapper writing to file
       - EncodeMapper SymbolTable access
-    * Replaced internal custom reference-counting (RefCounter) with
-      C++11 smart pointers where possible, and fixed associated
-      reference-counting bugs (1.5.1)
-    * When calling DeleteStates on a MutableFst with a shared impl, the impl
-      is set to a new empty impl rather than copying and deleting (1.5.1)
-    * Prepended `Pdt` to the Expand libraries and classes in the PDT
-      extension, and prepended `MPdt` to the Expand libraries and classes
-      in the MPDT extension, so that both can be used in the same compilation
-      unit (1.5.1)
-    * Added option to PDT Replace for compiling a strongly-regular RTN into a
-      bounded-stack PDT (1.5.1)
-    * Improved symbol table support for PDT Replace, including automatic
-      generation of parentheses symbols (1.5.1)
-    * Improvements to scripting API (1.5.1):
+   * Replaced internal custom reference-counting (RefCounter) with
+     C++11 smart pointers where possible, and fixed associated
+     reference-counting bugs (1.5.1)
+   * When calling DeleteStates on a MutableFst with a shared impl, the impl
+     is set to a new empty impl rather than copying and deleting (1.5.1)
+   * Prepended `Pdt` to the Expand libraries and classes in the PDT
+     extension, and prepended `MPdt` to the Expand libraries and classes
+     in the MPDT extension, so that both can be used in the same compilation
+     unit (1.5.1)
+   * Added option to PDT Replace for compiling a strongly-regular RTN into a
+     bounded-stack PDT (1.5.1)
+   * Improved symbol table support for PDT Replace, including automatic
+     generation of parentheses symbols (1.5.1)
+   * Improvements to scripting API (1.5.1):
       - Added methods for FST access and mutation
       - Added additional checks for arc/weight compatibility
       - WeightClass::One and WeightClass::Zero now require a specified weight
@@ -82,60 +90,60 @@ OpenFst: Release 1.5
       - Improved VectorFstClass constructors
       - Added linear-time check for cyclic dependencies in Replace
       - Added EncodeMapperClass, a template-free box for an EncodeMapper
-    * Improvements to the binaries (1.5.1):
+   * Improvements to the binaries (1.5.1):
       - Fixed no-op --precision flag to fstdraw (1.5.1)
       - Fixed no-op --file_list_input flag to farcreate (1.5.1)
-    * Improvements to the Python extension (1.5.1):
-      - Added methods for creating an empty mutable FST
-      - Added methods for FST access via state and arc iteration
-      - Added FST compilation from arclists (cf. fstcompile)
-      - Added FST printing and drawing
-      - Added FarReader and FarWriter classes.
-    * FarReader's GetFst method now returns a pointer (1.5.2)
-    * Fixed FSTERROR macro (1.5.2)
-    * Fixed build flags for dlopen (1.5.2)
-    * Consolidated Python extension into single module (1.5.2)
-    * Python add_arc now takes an Arc object (1.5.2)
-    * Adds optional minimization of non-deterministic FSTs (1.5.3)
-    * Mutation methods of the Python Fst object now support chaining (1.5.3)
-    * Scripting API and Python weight objects now support semiring arithmetic
-      (1.5.3)
-    * Adds RemoveSymbol method to SymbolTable (1.5.4)
-    * Prevents underflow when using LogProbArcSelector in random generation
-      (1.5.4)
-    * Makes random weight generators a single template class (1.5.4)
-    * Makes weight Properties constexpr where possible (1.5.4)
-    * Adds check for error when opening files when compiling strings into FARs
-      (1.5.4)
-    * Adds routines for parsing string flags to the scripting API (1.5.4)
+   * Improvements to the Python extension (1.5.1):
+      - Adds methods for creating an empty mutable FST
+      - Adds methods for FST access via state and arc iteration
+      - Adds FST compilation from arclists (cf. fstcompile)
+      - Adds FST printing and drawing
+      - Adds FarReader and FarWriter classes.
+   * FarReader's GetFst method now returns a pointer (1.5.2)
+   * Fixed FSTERROR macro (1.5.2)
+   * Fixed build flags for dlopen (1.5.2)
+   * Consolidated Python extension into single module (1.5.2)
+   * Python add_arc now takes an Arc object (1.5.2)
+   * Adds optional minimization of non-deterministic FSTs (1.5.3)
+   * Mutation methods of the Python Fst object now support chaining (1.5.3)
+   * Scripting API and Python weight objects now support semiring arithmetic
+     (1.5.3)
+   * Adds RemoveSymbol method to SymbolTable (1.5.4)
+   * Prevents underflow when using LogProbArcSelector in random generation
+     (1.5.4)
+   * Makes random weight generators a single template class (1.5.4)
+   * Makes weight Properties constexpr where possible (1.5.4)
+   * Adds check for error when opening files when compiling strings into FARs
+     (1.5.4)
+   * Adds routines for parsing string flags to the scripting API (1.5.4)
 
 OpenFst: Release 1.4
-    * Port to C++11 (1.4.0)
-    * Disambiguate function added (1.4.0)
-    * Isomorphic function added (1.4.0)
-    * Matcher interface augmented with Priority method.
-    * Special matchers (rho/sigma/phi) can match special symbols
-      on both input FSTs in composition/intersection provided at each
-      state pair they only match one side (1.4.0)
-    * Added ExplicitMatcher to suppress implicit matches (e.g. epsilon
-      self-loops) (1.4.0)
-    * Linear{Tagger,Classifier}Fst extensions added (1.4.0).
-    * Generalized state-reachable to work when input is cyclic (so long as no
-      final state is in a cycle). This ensures label-reachable (and hence label
-      lookahead) works with cyclic input (1.4.0)
-    * Added Condense to build the condensation graph (SCCs condensed to single
-      states) of an FST (1.4.0).
-    * Added an option to Reverse to specify whether a super-initial state
-      should always be created (1.4.0).
-    * Fixed bugs in FirstCacheStore, PowerWeight, and StringCompiler (1.4.0).
-    * Changed SymbolTable to use faster data structure (1.4.0).
-    * Added 'min' disambiguation in determinizaton to keep only the minimum
-      output in a non-functional transducer when plus=min/max
-      (flag --disambiguate_output) (1.4.1)
-    * Compiler issues in linear-fst fixed (1.4.1)
+   * Port to C++11 (1.4.0)
+   * Disambiguate function added (1.4.0)
+   * Isomorphic function added (1.4.0)
+   * Matcher interface augmented with Priority method.
+   * Special matchers (rho/sigma/phi) can match special symbols
+     on both input FSTs in composition/intersection provided at each
+     state pair they only match one side (1.4.0)
+   * Added ExplicitMatcher to suppress implicit matches (e.g. epsilon
+     self-loops) (1.4.0)
+   * Linear{Tagger,Classifier}Fst extensions added (1.4.0).
+   * Generalized state-reachable to work when input is cyclic (so long as no
+     final state is in a cycle). This ensures label-reachable (and hence label
+     lookahead) works with cyclic input (1.4.0)
+   * Added Condense to build the condensation graph (SCCs condensed to single
+     states) of an FST (1.4.0).
+   * Added an option to Reverse to specify whether a super-initial state
+     should always be created (1.4.0).
+   * Fixed bugs in FirstCacheStore, PowerWeight, and StringCompiler (1.4.0).
+   * Changed SymbolTable to use faster data structure (1.4.0).
+   * Added 'min' disambiguation in determinizaton to keep only the minimum
+     output in a non-functional transducer when plus=min/max
+     (flag --disambiguate_output) (1.4.1)
+   * Compiler issues in linear-fst fixed (1.4.1)
 
 OpenFst: Release 1.3
-    * Support for non-fatal exits on errors: (1.3.1)
+   * Support for non-fatal exits on errors: (1.3.1)
       - Added FLAGS_fst_error_fatal: FST errors are
         fatal if true (default); o.w. return objects flagged as bad:
         e.g., FSTs - kError
@@ -143,52 +151,52 @@ OpenFst: Release 1.3
       - Added kError property bit signifying bad FST
       - Added  NoWeight() method to FST weight requirements that returns
         weight that is not a Member().
-    * Various improvements to the FAR extensions (1.3.1)
+   * Various improvements to the FAR extensions (1.3.1)
       - a single FST is now a FAR type
       - FLAGS_initial_symbols: Uses the symbol table from the
         first FST in the archive for all entries"
       - Input/output to standard input/output for some FAR and arc types
-    * --with-icu configuration option no longer needed (1.3.1)
-    * Improved flags usage esp. if use SET_FLAGS not SetFlags/InitFst (1.3.2)
-    * Added 'fst' as possible far writer type (1.3.2)
-    * phi matcher can now accept 0 as the phi label (1.3.2)
-    * Added ngram-fst extension (1.3.2)
-    * Improved performance of PDT composition (1.3.3)
-    * Memory-map support (1.3.3)
-    * Fixed cross-FST serialization issues (1.3.3)
-    * Fixed NGramFst off-by-one issue (1.3.3)
-    * farextract now allows one to specify a list of comma-separated keys,
-      including key ranges (1.3.3)
-    * Fixed bug in PDT replace that could cause close paren IDs to collide
-      with open paren IDs (1.3.4)
+   * --with-icu configuration option no longer needed (1.3.1)
+   * Improved flags usage esp. if use SET_FLAGS not SetFlags/InitFst (1.3.2)
+   * Added 'fst' as possible far writer type (1.3.2)
+   * phi matcher can now accept 0 as the phi label (1.3.2)
+   * Added ngram-fst extension (1.3.2)
+   * Improved performance of PDT composition (1.3.3)
+   * Memory-map support (1.3.3)
+   * Fixed cross-FST serialization issues (1.3.3)
+   * Fixed NGramFst off-by-one issue (1.3.3)
+   * farextract now allows one to specify a list of comma-separated keys,
+     including key ranges (1.3.3)
+   * Fixed bug in PDT replace that could cause close paren IDs to collide
+     with open paren IDs (1.3.4)
 
 OpenFst: Release 1.2
-    * Added lookahead matching and filtering for faster composition
-    * Added EditFst for mutation of o.w. immutable FSTs
-    * Added script sub-namespace defining type FstClass, a non-templated
-      Fst<Arc> to hold the arc template type internally. This and FST
-      operations on it allow easier I/O and scripting at the cost of some
-      runtime dispatching.
-    * Added per-arc-iterator control of Fst caching.
-    * Added PowerWeight and Power Arc.
-    * Added SparsePowerWeight and SparsePowerArc (1.2.4)
-    * Added SignedLogWeight and SignedLogArc (1.2.4)
-    * Added ExpectationWeight and ExpectationArc (1.2.4)
-    * Added AStarQueue, PruneQueue and NaturalPruneQueue disciplines (1.2.6)
-    * Added Log64Weight and Log64Arc to FST library throughout, including 
-      support throughout scripts/bins/dsos (1.2.8)
-    * Added delayed RandGenFst that outputs tree of paths weighted
-      by count (1.2.8)
-    * Added fstsymbols shell-level command
-    * Added total weight removal option to pushing
-    * Changed methods for symbol table mutation:
-      use MutableInputSymbols()/MutableOutputSymbols().
-    * Numerous efficiency improvements esp in composition, replace, and caching
-    * Made "fstmap" handle semiring conversion by adding "to_std", "to_log"
-      and "to_log64" as supported 'map_type' arguments (1.2.8).
-    * Made the destructive implementation of RmEpsilon skip over states
-      admitting no non-epsilon incoming transition (1.2.8).
-    * Fixed numerous bugs (1.2 through 1.2.9) including:
+   * Added lookahead matching and filtering for faster composition
+   * Added EditFst for mutation of o.w. immutable FSTs
+   * Added script sub-namespace defining type FstClass, a non-templated
+     Fst<Arc> to hold the arc template type internally. This and FST
+     operations on it allow easier I/O and scripting at the cost of some
+     runtime dispatching.
+   * Added per-arc-iterator control of Fst caching.
+   * Added PowerWeight and Power Arc.
+   * Added SparsePowerWeight and SparsePowerArc (1.2.4)
+   * Added SignedLogWeight and SignedLogArc (1.2.4)
+   * Added ExpectationWeight and ExpectationArc (1.2.4)
+   * Added AStarQueue, PruneQueue and NaturalPruneQueue disciplines (1.2.6)
+   * Added Log64Weight and Log64Arc to FST library throughout, including 
+     support throughout scripts/bins/dsos (1.2.8)
+   * Added delayed RandGenFst that outputs tree of paths weighted
+     by count (1.2.8)
+   * Added fstsymbols shell-level command
+   * Added total weight removal option to pushing
+   * Changed methods for symbol table mutation:
+     use MutableInputSymbols()/MutableOutputSymbols().
+   * Numerous efficiency improvements esp in composition, replace, and caching
+   * Made "fstmap" handle semiring conversion by adding "to_std", "to_log"
+     and "to_log64" as supported 'map_type' arguments (1.2.8).
+   * Made the destructive implementation of RmEpsilon skip over states
+     admitting no non-epsilon incoming transition (1.2.8).
+   * Fixed numerous bugs (1.2 through 1.2.9) including:
       - improper types of some approximation deltas
       - sub-optimal hashing functions
       - issues in internal reuse of shortest distance
@@ -207,46 +215,46 @@ OpenFst: Release 1.2
       - Fixed missing <functional> includes (1.2.9)
       - Fixed reused local variable names (1.2.9)
       - Fixed passing string by reference in FstDraw args (1.2.9)
-    * Added extensions directories including:
+   * Added extensions directories including:
       - finite-state archive (FAR) utilities,
         added stlist format supporting writing/reading to/from standard out/in
         at the library-level (1.2.8)
-      - compact fsts
-      - lookahead fsts
+      - compact FSTs
+      - lookahead FSTs
       - pushdown transducers (improved in 1.2.1 through 1.2.7).
-    * Added StateMap/StateMapFst; renamed Map/MapFst to ArcMap/ArcMapFst;
-      map/MapFst retained (but deprecated) (1.2.9)
-    * Deleted ArcSum() and ArcMerge; use StateMap w/ ArcSumMapper and
-      ArcUniqueMapper (1.2.9).
-    * Incremented version of ConstFst/CompactFsts to stop memory alignment
-      that fails on pipes. Made old version raises errors when read on
-      pipes (1.2.9).
-    * Improved determinize hash (1.2.9)
-    * Removed stdio uses (1.2.10)
-    * Fixed library ordering issues esp. with newer GNU build tools (1.2.10)
+   * Added StateMap/StateMapFst; renamed Map/MapFst to ArcMap/ArcMapFst;
+     map/MapFst retained (but deprecated) (1.2.9)
+   * Deleted ArcSum() and ArcMerge; use StateMap w/ ArcSumMapper and
+     ArcUniqueMapper (1.2.9).
+   * Incremented version of ConstFst/CompactFsts to stop memory alignment
+     that fails on pipes. Made old version raises errors when read on
+     pipes (1.2.9).
+   * Improved determinize hash (1.2.9)
+   * Removed stdio uses (1.2.10)
+   * Fixed library ordering issues esp. with newer GNU build tools (1.2.10)
 
 OpenFst: Release 1.1
-    * Added compat.h to src/include/fst to fix missing defines
-    * Fixed bug in acyclic minimization that led to non-minimal
-      (but equivalent) results
-    * Fixed missing FST typedef in various matchers in matcher.h
-      so that they can be cascaded
-    * Opened file streams binary where appropriate
+   * Added compat.h to src/include/fst to fix missing defines
+   * Fixed bug in acyclic minimization that led to non-minimal
+     (but equivalent) results
+   * Fixed missing FST typedef in various matchers in matcher.h
+     so that they can be cascaded
+   * Opened file streams binary where appropriate
 
 OpenFst: Release 1.0 (Additions to beta version):
-    * Matcher class added for matching labels at FST states. Includes
-      special matchers for sigma (any), rho ('rest'), and phi ('fail')
-      labels.
-    * Composition generalized with arbitrary filters, matchers, and state
-      tables.
-    * Sequence and matching composition filters provided. (see compose.h,
-      compose-filter.h, matcher.h, state-table.h)
-    * Unique n-best (see shortest-path.h)
-    * Pruning in determinization and epsilon removal (see determinize.h,
-      rmepsilon.h)
-    * New Fst class:
-       * Compact Fsts for space-efficient representation (see compact-fst.h)
-    * New Weight classes:
-       * MinMax
-       * Lexicographic
-    * Miscellaneous bug fixes
+   * Matcher class added for matching labels at FST states. Includes
+     special matchers for sigma (any), rho ('rest'), and phi ('fail')
+     labels.
+   * Composition generalized with arbitrary filters, matchers, and state
+     tables.
+   * Sequence and matching composition filters provided. (see compose.h,
+     compose-filter.h, matcher.h, state-table.h)
+   * Unique n-best (see shortest-path.h)
+   * Pruning in determinization and epsilon removal (see determinize.h,
+     rmepsilon.h)
+   * New Fst class:
+      - Compact FSTs for space-efficient representation (see compact-fst.h)
+   * New Weight classes:
+      - MinMax
+      - Lexicographic
+   * Miscellaneous bug fixes
diff --git a/README b/README
index e7626e1..7becbe5 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-OpenFst: Release 1.6.9.
+OpenFst: Release 1.7.0.
 
 OpenFst is a library for constructing, combining, optimizing, and searching
 weighted finite-state transducers (FSTs).
index 418c17b..2e6633d 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for OpenFst 1.6.9.
+# Generated by GNU Autoconf 2.69 for OpenFst 1.7.0.
 #
 # Report bugs to <help@www.openfst.org>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='OpenFst'
 PACKAGE_TARNAME='openfst'
-PACKAGE_VERSION='1.6.9'
-PACKAGE_STRING='OpenFst 1.6.9'
+PACKAGE_VERSION='1.7.0'
+PACKAGE_STRING='OpenFst 1.7.0'
 PACKAGE_BUGREPORT='help@www.openfst.org'
 PACKAGE_URL=''
 
@@ -1395,7 +1395,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures OpenFst 1.6.9 to adapt to many kinds of systems.
+\`configure' configures OpenFst 1.7.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1466,7 +1466,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of OpenFst 1.6.9:";;
+     short | recursive ) echo "Configuration of OpenFst 1.7.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1598,7 +1598,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-OpenFst configure 1.6.9
+OpenFst configure 1.7.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1993,11 +1993,53 @@ fi
   as_fn_set_status $ac_retval
 
 } # ac_fn_cxx_try_link
+
+# ac_fn_cxx_try_run LINENO
+# ------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_cxx_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_run
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by OpenFst $as_me 1.6.9, which was
+It was created by OpenFst $as_me 1.7.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2860,7 +2902,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='openfst'
- VERSION='1.6.9'
+ VERSION='1.7.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -5896,7 +5938,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd* | netbsdelf*-gnu)
+netbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
   else
@@ -9569,9 +9611,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
   openbsd* | bitrig*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    link_all_deplibs=no
-    ;;
   esac
 
   ld_shlibs=yes
@@ -9826,7 +9865,7 @@ _LT_EOF
       fi
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
        archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
        wlarc=
@@ -10496,7 +10535,6 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; }
        if test yes = "$lt_cv_irix_exported_symbol"; then
           archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
        fi
-       link_all_deplibs=no
       else
        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
        archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
@@ -10518,7 +10556,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; }
       esac
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
        archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
       else
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -14539,7 +14565,7 @@ lt_prog_compiler_static_CXX=
            ;;
        esac
        ;;
-      netbsd* | netbsdelf*-gnu)
+      netbsd*)
        ;;
       *qnx* | *nto*)
         # QNX uses GNU C++, but need to define -shared option too, otherwise
@@ -14914,9 +14940,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
       ;;
     esac
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    link_all_deplibs_CXX=no
-    ;;
   *)
     export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
     ;;
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
 libfstdir=$with_libfstdir
 
 
+# Flags may be changed after configuring, so this is checked again by
+# weight_test.cc.  The check here is to save time in the common case,
+# or when someone does not run `make check`.
+if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+                 #include <cstdio>
+
+                 template <typename T>
+                 bool FloatEqIsReflexive(T m) {
+                   volatile T x = 1.111;
+                   x *= m;
+
+                   T y = 1.111;
+                   y *= m;
+
+                   return x == y;
+                 }
+
+int
+main ()
+{
+
+                 volatile double test_value = 1.1;
+                 if (!FloatEqIsReflexive(static_cast<float>(test_value))) {
+                   printf("float FAIL\n");
+                   return 1;
+                 }
+                 if (!FloatEqIsReflexive(test_value)) {
+                   printf("double FAIL\n");
+                   return 1;
+                 }
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+  echo "Float equality is good"
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Test float equality failed! Compile with -msse -mfpmath=sse if using g++.
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
 $as_echo_n "checking for dlopen in -ldl... " >&6; }
 if ${ac_cv_lib_dl_dlopen+:} false; then :
@@ -17391,7 +17458,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by OpenFst $as_me 1.6.9, which was
+This file was extended by OpenFst $as_me 1.7.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -17457,7 +17524,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-OpenFst config.status 1.6.9
+OpenFst config.status 1.7.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -18693,6 +18760,7 @@ $as_echo X"$file" |
     cat <<_LT_EOF >> "$cfgfile"
 #! $SHELL
 # Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
 
 # Provide generalized library-building support services.
index bf5a42f..d375d33 100644 (file)
@@ -1,4 +1,4 @@
-AC_INIT([OpenFst], [1.6.9], [help@www.openfst.org])
+AC_INIT([OpenFst], [1.7.0], [help@www.openfst.org])
 AM_INIT_AUTOMAKE([foreign nostdinc -Wall -Werror subdir-objects])
 AM_PROG_AR
 
@@ -141,6 +141,39 @@ AC_ARG_WITH([libfstdir],
 
 AC_SUBST([libfstdir], $with_libfstdir)
 
+# Flags may be changed after configuring, so this is checked again by
+# weight_test.cc.  The check here is to save time in the common case,
+# or when someone does not run `make check`.
+AC_RUN_IFELSE([AC_LANG_PROGRAM([
+                 #include <cstdio>
+
+                 template <typename T>
+                 bool FloatEqIsReflexive(T m) {
+                   volatile T x = 1.111;
+                   x *= m;
+
+                   T y = 1.111;
+                   y *= m;
+
+                   return x == y;
+                 }
+               ], [
+                 volatile double test_value = 1.1;
+                 if (!FloatEqIsReflexive(static_cast<float>(test_value))) {
+                   printf("float FAIL\n");
+                   return 1;
+                 }
+                 if (!FloatEqIsReflexive(test_value)) {
+                   printf("double FAIL\n");
+                   return 1;
+                 }
+               ])],
+              [echo "Float equality is good"],
+              [AC_MSG_FAILURE(m4_normalize([
+                   Test float equality failed!
+                   Compile with -msse -mfpmath=sse if using g++.
+              ]))])
+
 AC_CHECK_LIB([dl], dlopen, [DL_LIBS=-ldl])
 AC_SUBST([DL_LIBS])
 
index a736cf9..b6f1800 100644 (file)
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -31,7 +31,7 @@
 
 PROGRAM=libtool
 PACKAGE=libtool
-VERSION="2.4.6 Debian-2.4.6-2"
+VERSION=2.4.6
 package_revision=2.4.6
 
 
@@ -2068,12 +2068,12 @@ include the following information:
        compiler:       $LTCC
        compiler flags: $LTCFLAGS
        linker:         $LD (gnu? $with_gnu_ld)
-       version:        $progname $scriptversion Debian-2.4.6-2
+       version:        $progname (GNU libtool) 2.4.6
        automake:       `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
        autoconf:       `($AUTOCONF --version) 2>/dev/null |$SED 1q`
 
 Report bugs to <bug-libtool@gnu.org>.
-GNU libtool home page: <http://www.gnu.org/s/libtool/>.
+GNU libtool home page: <http://www.gnu.org/software/libtool/>.
 General help using GNU software: <http://www.gnu.org/gethelp/>."
     exit 0
 }
@@ -7220,6 +7220,11 @@ func_mode_link ()
        arg=$func_stripname_result
        ;;
 
+      -Wl,--as-needed)
+       deplibs="$deplibs $arg"
+       continue
+       ;;
+
       -Wl,*)
        func_stripname '-Wl,' '' "$arg"
        args=$func_stripname_result
@@ -7272,13 +7277,10 @@ func_mode_link ()
       # -tp=*                Portland pgcc target processor selection
       # --sysroot=*          for sysroot support
       # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
-      # -specs=*             GCC specs files
       # -stdlib=*            select c++ std lib with clang
-      # -fsanitize=*         Clang/GCC memory and address sanitizer
       -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
       -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
-      -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
-      -specs=*|-fsanitize=*)
+      -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*)
         func_quote_for_eval "$arg"
        arg=$func_quote_for_eval_result
         func_append compile_command " $arg"
@@ -7527,6 +7529,7 @@ func_mode_link ()
 
     case $linkmode in
     lib)
+       as_needed_flag=
        passes="conv dlpreopen link"
        for file in $dlfiles $dlprefiles; do
          case $file in
@@ -7538,6 +7541,7 @@ func_mode_link ()
        done
        ;;
     prog)
+       as_needed_flag=
        compile_deplibs=
        finalize_deplibs=
        alldeplibs=false
@@ -7571,10 +7575,7 @@ func_mode_link ()
        case $pass in
        dlopen) libs=$dlfiles ;;
        dlpreopen) libs=$dlprefiles ;;
-       link)
-         libs="$deplibs %DEPLIBS%"
-         test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
-         ;;
+       link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
        esac
       fi
       if test lib,dlpreopen = "$linkmode,$pass"; then
@@ -7610,6 +7611,15 @@ func_mode_link ()
        lib=
        found=false
        case $deplib in
+       -Wl,--as-needed)
+         if test prog,link = "$linkmode,$pass" ||
+            test lib,link = "$linkmode,$pass"; then
+           as_needed_flag="$deplib "
+         else
+           deplibs="$deplib $deplibs"
+         fi
+         continue
+         ;;
        -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
         |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
          if test prog,link = "$linkmode,$pass"; then
@@ -7893,19 +7903,19 @@ func_mode_link ()
            # It is a libtool convenience library, so add in its objects.
            func_append convenience " $ladir/$objdir/$old_library"
            func_append old_convenience " $ladir/$objdir/$old_library"
-           tmp_libs=
-           for deplib in $dependency_libs; do
-             deplibs="$deplib $deplibs"
-             if $opt_preserve_dup_deps; then
-               case "$tmp_libs " in
-               *" $deplib "*) func_append specialdeplibs " $deplib" ;;
-               esac
-             fi
-             func_append tmp_libs " $deplib"
-           done
          elif test prog != "$linkmode" && test lib != "$linkmode"; then
            func_fatal_error "'$lib' is not a convenience library"
          fi
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           deplibs="$deplib $deplibs"
+           if $opt_preserve_dup_deps; then
+             case "$tmp_libs " in
+             *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+             esac
+           fi
+           func_append tmp_libs " $deplib"
+         done
          continue
        fi # $pass = conv
 
@@ -8829,9 +8839,6 @@ func_mode_link ()
            revision=$number_minor
            lt_irix_increment=no
            ;;
-         *)
-           func_fatal_configuration "$modename: unknown library version type '$version_type'"
-           ;;
          esac
          ;;
        no)
@@ -10030,6 +10037,13 @@ EOF
          test "X$libobjs" = "X " && libobjs=
        fi
 
+       # A bit hacky. I had wanted to add \$as_needed_flag to archive_cmds instead, but that
+       # comes from libtool.m4 which is part of the project being built. This should put it
+       # in the right place though.
+       if test lib,link = "$linkmode,$pass" && test -n "$as_needed_flag"; then
+         libobjs=$as_needed_flag$libobjs
+       fi
+
        save_ifs=$IFS; IFS='~'
        for cmd in $cmds; do
          IFS=$sp$nl
@@ -10262,8 +10276,8 @@ EOF
       compile_deplibs=$new_libs
 
 
-      func_append compile_command " $compile_deplibs"
-      func_append finalize_command " $finalize_deplibs"
+      func_append compile_command " $as_needed_flag $compile_deplibs"
+      func_append finalize_command " $as_needed_flag $finalize_deplibs"
 
       if test -n "$rpath$xrpath"; then
        # If the user specified any rpath flags, then add them.
index ee80844..a3bc337 100644 (file)
@@ -728,6 +728,7 @@ _LT_CONFIG_SAVE_COMMANDS([
     cat <<_LT_EOF >> "$cfgfile"
 #! $SHELL
 # Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
 
 # Provide generalized library-building support services.
@@ -2886,18 +2887,6 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -3557,7 +3546,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd* | netbsdelf*-gnu)
+netbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
   else
@@ -4435,7 +4424,7 @@ m4_if([$1], [CXX], [
            ;;
        esac
        ;;
-      netbsd* | netbsdelf*-gnu)
+      netbsd*)
        ;;
       *qnx* | *nto*)
         # QNX uses GNU C++, but need to define -shared option too, otherwise
@@ -4947,9 +4936,6 @@ m4_if([$1], [CXX], [
       ;;
     esac
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    _LT_TAGVAR(link_all_deplibs, $1)=no
-    ;;
   *)
     _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
     ;;
@@ -5012,9 +4998,6 @@ dnl Note also adjust exclude_expsyms for C++ above.
   openbsd* | bitrig*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    _LT_TAGVAR(link_all_deplibs, $1)=no
-    ;;
   esac
 
   _LT_TAGVAR(ld_shlibs, $1)=yes
@@ -5269,7 +5252,7 @@ _LT_EOF
       fi
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
        _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
        wlarc=
@@ -5790,7 +5773,6 @@ _LT_EOF
        if test yes = "$lt_cv_irix_exported_symbol"; then
           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
        fi
-       _LT_TAGVAR(link_all_deplibs, $1)=no
       else
        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
@@ -5812,7 +5794,7 @@ _LT_EOF
       esac
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
        _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
       else
index 82a70d5..d31fb9e 100644 (file)
@@ -10,8 +10,8 @@
 
 #include <fst/flags.h>
 #include <fst/log.h>
-#include <fst/script/getters.h>
 #include <fst/script/difference.h>
+#include <fst/script/getters.h>
 
 DECLARE_string(compose_filter);
 DECLARE_bool(connect);
index 7c2290d..3e45833 100644 (file)
@@ -6,7 +6,7 @@ libfst_LTLIBRARIES = compact8_acceptor-fst.la compact8_string-fst.la compact8_un
 lib_LTLIBRARIES = libfstcompact.la
 
 libfstcompact_la_SOURCES = compact8_acceptor-fst.cc compact8_string-fst.cc compact8_unweighted-fst.cc compact8_unweighted_acceptor-fst.cc compact8_weighted_string-fst.cc compact16_acceptor-fst.cc compact16_string-fst.cc compact16_unweighted-fst.cc compact16_unweighted_acceptor-fst.cc compact16_weighted_string-fst.cc compact64_acceptor-fst.cc compact64_string-fst.cc compact64_unweighted-fst.cc compact64_unweighted_acceptor-fst.cc compact64_weighted_string-fst.cc
-libfstcompact_la_LDFLAGS = -version-info 13:0:0
+libfstcompact_la_LDFLAGS = -version-info 14:0:0
 libfstcompact_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 
 compact8_acceptor_fst_la_SOURCES = compact8_acceptor-fst.cc
index 02db95e..5acdc62 100644 (file)
@@ -514,7 +514,7 @@ AM_CPPFLAGS = -I$(srcdir)/../../include $(ICU_CPPFLAGS)
 libfst_LTLIBRARIES = compact8_acceptor-fst.la compact8_string-fst.la compact8_unweighted-fst.la compact8_unweighted_acceptor-fst.la compact8_weighted_string-fst.la compact16_acceptor-fst.la compact16_string-fst.la compact16_unweighted-fst.la compact16_unweighted_acceptor-fst.la compact16_weighted_string-fst.la compact64_acceptor-fst.la compact64_string-fst.la compact64_unweighted-fst.la compact64_unweighted_acceptor-fst.la compact64_weighted_string-fst.la
 lib_LTLIBRARIES = libfstcompact.la
 libfstcompact_la_SOURCES = compact8_acceptor-fst.cc compact8_string-fst.cc compact8_unweighted-fst.cc compact8_unweighted_acceptor-fst.cc compact8_weighted_string-fst.cc compact16_acceptor-fst.cc compact16_string-fst.cc compact16_unweighted-fst.cc compact16_unweighted_acceptor-fst.cc compact16_weighted_string-fst.cc compact64_acceptor-fst.cc compact64_string-fst.cc compact64_unweighted-fst.cc compact64_unweighted_acceptor-fst.cc compact64_weighted_string-fst.cc
-libfstcompact_la_LDFLAGS = -version-info 13:0:0
+libfstcompact_la_LDFLAGS = -version-info 14:0:0
 libfstcompact_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 compact8_acceptor_fst_la_SOURCES = compact8_acceptor-fst.cc
 compact8_acceptor_fst_la_LDFLAGS = -module
index de94d5d..fa15beb 100644 (file)
@@ -8,7 +8,11 @@ namespace fst {
 
 static FstRegisterer<CompactAcceptorFst<StdArc, uint16>>
     CompactAcceptorFst_StdArc_uint16_registerer;
+
 static FstRegisterer<CompactAcceptorFst<LogArc, uint16>>
     CompactAcceptorFst_LogArc_uint16_registerer;
 
+static FstRegisterer<CompactAcceptorFst<Log64Arc, uint16>>
+    CompactAcceptorFst_Log64Arc_uint16_registerer;
+
 }  // namespace fst
index b3b4b2c..1bb013e 100644 (file)
@@ -8,7 +8,11 @@ namespace fst {
 
 static FstRegisterer<CompactStringFst<StdArc, uint16>>
     CompactStringFst_StdArc_uint16_registerer;
+
 static FstRegisterer<CompactStringFst<LogArc, uint16>>
     CompactStringFst_LogArc_uint16_registerer;
 
+static FstRegisterer<CompactStringFst<Log64Arc, uint16>>
+    CompactStringFst_Log64Arc_uint16_registerer;
+
 }  // namespace fst
index 21fc247..95b72c6 100644 (file)
@@ -8,7 +8,12 @@ namespace fst {
 
 static FstRegisterer<CompactUnweightedFst<StdArc, uint16>>
     CompactUnweightedFst_StdArc_uint16_registerer;
+
 static FstRegisterer<CompactUnweightedFst<LogArc, uint16>>
     CompactUnweightedFst_LogArc_uint16_registerer;
 
+static FstRegisterer<CompactUnweightedFst<Log64Arc, uint16>>
+    CompactUnweightedFst_Log64Arc_uint16_registerer;
+
+
 }  // namespace fst
index 13cfb4d..533a0a1 100644 (file)
@@ -9,8 +9,13 @@ namespace fst {
 static FstRegisterer<
     CompactUnweightedAcceptorFst<StdArc, uint16>>
     CompactUnweightedAcceptorFst_StdArc_uint16_registerer;
+
 static FstRegisterer<
     CompactUnweightedAcceptorFst<LogArc, uint16>>
     CompactUnweightedAcceptorFst_LogArc_uint16_registerer;
 
+static FstRegisterer<
+    CompactUnweightedAcceptorFst<Log64Arc, uint16>>
+    CompactUnweightedAcceptorFst_Log64Arc_uint16_registerer;
+
 }  // namespace fst
index baa9917..27daceb 100644 (file)
@@ -14,4 +14,8 @@ static FstRegisterer<
     CompactWeightedStringFst<LogArc, uint16>>
     CompactWeightedStringFst_LogArc_uint16_registerer;
 
+static FstRegisterer<
+    CompactWeightedStringFst<Log64Arc, uint16>>
+    CompactWeightedStringFst_Log64Arc_uint16_registerer;
+
 }  // namespace fst
index eb410b8..951d0f7 100644 (file)
@@ -12,4 +12,7 @@ static FstRegisterer<CompactAcceptorFst<StdArc, uint64>>
 static FstRegisterer<CompactAcceptorFst<LogArc, uint64>>
     CompactAcceptorFst_LogArc_uint64_registerer;
 
+static FstRegisterer<CompactAcceptorFst<Log64Arc, uint64>>
+    CompactAcceptorFst_Log64Arc_uint64_registerer;
+
 }  // namespace fst
index 708be49..ab77014 100644 (file)
@@ -8,7 +8,11 @@ namespace fst {
 
 static FstRegisterer<CompactStringFst<StdArc, uint64>>
     CompactStringFst_StdArc_uint64_registerer;
+
 static FstRegisterer<CompactStringFst<LogArc, uint64>>
     CompactStringFst_LogArc_uint64_registerer;
 
+static FstRegisterer<CompactStringFst<Log64Arc, uint64>>
+    CompactStringFst_Log64Arc_uint64_registerer;
+
 }  // namespace fst
index 01f6651..366a00f 100644 (file)
@@ -8,7 +8,11 @@ namespace fst {
 
 static FstRegisterer<CompactUnweightedFst<StdArc, uint64>>
     CompactUnweightedFst_StdArc_uint64_registerer;
+
 static FstRegisterer<CompactUnweightedFst<LogArc, uint64>>
     CompactUnweightedFst_LogArc_uint64_registerer;
 
+static FstRegisterer<CompactUnweightedFst<Log64Arc, uint64>>
+    CompactUnweightedFst_Log64Arc_uint64_registerer;
+
 }  // namespace fst
index f8f7b70..db819db 100644 (file)
@@ -9,8 +9,13 @@ namespace fst {
 static FstRegisterer<
     CompactUnweightedAcceptorFst<StdArc, uint64>>
     CompactUnweightedAcceptorFst_StdArc_uint64_registerer;
+
 static FstRegisterer<
     CompactUnweightedAcceptorFst<LogArc, uint64>>
     CompactUnweightedAcceptorFst_LogArc_uint64_registerer;
 
+static FstRegisterer<
+    CompactUnweightedAcceptorFst<Log64Arc, uint64>>
+    CompactUnweightedAcceptorFst_Log64Arc_uint64_registerer;
+
 }  // namespace fst
index 4b439dc..001af1b 100644 (file)
@@ -9,8 +9,13 @@ namespace fst {
 static FstRegisterer<
     CompactWeightedStringFst<StdArc, uint64>>
     CompactWeightedStringFst_StdArc_uint64_registerer;
+
 static FstRegisterer<
     CompactWeightedStringFst<LogArc, uint64>>
     CompactWeightedStringFst_LogArc_uint64_registerer;
 
+static FstRegisterer<
+    CompactWeightedStringFst<Log64Arc, uint64>>
+    CompactWeightedStringFst_Log64Arc_uint64_registerer;
+
 }  // namespace fst
index 5de2665..7da949e 100644 (file)
@@ -8,7 +8,11 @@ namespace fst {
 
 static FstRegisterer<CompactAcceptorFst<StdArc, uint8>>
     CompactAcceptorFst_StdArc_uint8_registerer;
+
 static FstRegisterer<CompactAcceptorFst<LogArc, uint8>>
     CompactAcceptorFst_LogArc_uint8_registerer;
 
+static FstRegisterer<CompactAcceptorFst<Log64Arc, uint8>>
+    CompactAcceptorFst_Log64Arc_uint8_registerer;
+
 }  // namespace fst
index 384875b..d97d02f 100644 (file)
@@ -8,7 +8,11 @@ namespace fst {
 
 static FstRegisterer<CompactStringFst<StdArc, uint8>>
     CompactStringFst_StdArc_uint8_registerer;
+
 static FstRegisterer<CompactStringFst<LogArc, uint8>>
     CompactStringFst_LogArc_uint8_registerer;
 
+static FstRegisterer<CompactStringFst<Log64Arc, uint8>>
+    CompactStringFst_Log64Arc_uint8_registerer;
+
 }  // namespace fst
index 7769096..19ce43a 100644 (file)
@@ -8,7 +8,11 @@ namespace fst {
 
 static FstRegisterer<CompactUnweightedFst<StdArc, uint8>>
     CompactUnweightedFst_StdArc_uint8_registerer;
+
 static FstRegisterer<CompactUnweightedFst<LogArc, uint8>>
     CompactUnweightedFst_LogArc_uint8_registerer;
 
+static FstRegisterer<CompactUnweightedFst<Log64Arc, uint8>>
+    CompactUnweightedFst_Log64Arc_uint8_registerer;
+
 }  // namespace fst
index 26d0483..72ae73e 100644 (file)
@@ -9,8 +9,13 @@ namespace fst {
 static FstRegisterer<
     CompactUnweightedAcceptorFst<StdArc, uint8>>
     CompactUnweightedAcceptorFst_StdArc_uint8_registerer;
+
 static FstRegisterer<
     CompactUnweightedAcceptorFst<LogArc, uint8>>
     CompactUnweightedAcceptorFst_LogArc_uint8_registerer;
 
+static FstRegisterer<
+    CompactUnweightedAcceptorFst<Log64Arc, uint8>>
+    CompactUnweightedAcceptorFst_Log64Arc_uint8_registerer;
+
 }  // namespace fst
index 8506859..0c92127 100644 (file)
@@ -9,8 +9,13 @@ namespace fst {
 static FstRegisterer<
     CompactWeightedStringFst<StdArc, uint8>>
     CompactWeightedStringFst_StdArc_uint8_registerer;
+
 static FstRegisterer<
     CompactWeightedStringFst<LogArc, uint8>>
     CompactWeightedStringFst_LogArc_uint8_registerer;
 
+static FstRegisterer<
+    CompactWeightedStringFst<Log64Arc, uint8>>
+    CompactWeightedStringFst_Log64Arc_uint8_registerer;
+
 }  // namespace fst
index e788ebe..23bccfd 100644 (file)
@@ -14,7 +14,7 @@ endif
 
 if HAVE_SCRIPT
 libfstcompressscript_la_SOURCES = compress-script.cc
-libfstcompressscript_la_LDFLAGS = -version-info 13:0:0
+libfstcompressscript_la_LDFLAGS = -version-info 14:0:0
 libfstcompressscript_la_LIBADD = \
         ../../script/libfstscript.la \
         ../../lib/libfst.la -lz -lm $(DL_LIBS)
index ceceb92..ef143cd 100644 (file)
@@ -376,7 +376,7 @@ AM_CPPFLAGS = -I$(srcdir)/../../include $(ICU_CPPFLAGS)
 @HAVE_BIN_TRUE@fstcompress_SOURCES = fstcompress.cc
 @HAVE_BIN_TRUE@fstrandmod_SOURCES = fstrandmod.cc
 @HAVE_SCRIPT_TRUE@libfstcompressscript_la_SOURCES = compress-script.cc
-@HAVE_SCRIPT_TRUE@libfstcompressscript_la_LDFLAGS = -version-info 13:0:0
+@HAVE_SCRIPT_TRUE@libfstcompressscript_la_LDFLAGS = -version-info 14:0:0
 @HAVE_SCRIPT_TRUE@libfstcompressscript_la_LIBADD = \
 @HAVE_SCRIPT_TRUE@        ../../script/libfstscript.la \
 @HAVE_SCRIPT_TRUE@        ../../lib/libfst.la -lz -lm $(DL_LIBS)
index 5f5fbbc..b9ff31c 100644 (file)
@@ -6,7 +6,7 @@ libfst_LTLIBRARIES = const8-fst.la const16-fst.la const64-fst.la
 lib_LTLIBRARIES = libfstconst.la
 
 libfstconst_la_SOURCES = const8-fst.cc const16-fst.cc const64-fst.cc
-libfstconst_la_LDFLAGS = -version-info 13:0:0 -lm $(DL_LIBS)
+libfstconst_la_LDFLAGS = -version-info 14:0:0 -lm $(DL_LIBS)
 libfstconst_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 
 const8_fst_la_SOURCES = const8-fst.cc
index 5e06e61..c93a36c 100644 (file)
@@ -371,7 +371,7 @@ AM_CPPFLAGS = -I$(srcdir)/../../include $(ICU_CPPFLAGS)
 libfst_LTLIBRARIES = const8-fst.la const16-fst.la const64-fst.la
 lib_LTLIBRARIES = libfstconst.la
 libfstconst_la_SOURCES = const8-fst.cc const16-fst.cc const64-fst.cc
-libfstconst_la_LDFLAGS = -version-info 13:0:0 -lm $(DL_LIBS)
+libfstconst_la_LDFLAGS = -version-info 14:0:0 -lm $(DL_LIBS)
 libfstconst_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 const8_fst_la_SOURCES = const8-fst.cc
 const8_fst_la_LDFLAGS = -module
index 41d0f3d..e83efd8 100644 (file)
@@ -7,13 +7,13 @@ lib_LTLIBRARIES = libfstfar.la
 endif
 
 libfstfar_la_SOURCES = sttable.cc stlist.cc
-libfstfar_la_LDFLAGS = -version-info 13:0:0
+libfstfar_la_LDFLAGS = -version-info 14:0:0
 libfstfar_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 
 if HAVE_SCRIPT
 libfstfarscript_la_SOURCES = far-class.cc farscript.cc getters.cc script-impl.cc \
                              strings.cc
-libfstfarscript_la_LDFLAGS = -version-info 13:0:0
+libfstfarscript_la_LDFLAGS = -version-info 14:0:0
 libfstfarscript_la_LIBADD = \
     libfstfar.la ../../script/libfstscript.la \
         ../../lib/libfst.la -lm $(DL_LIBS)
index f555099..c916e45 100644 (file)
@@ -426,12 +426,12 @@ AM_CPPFLAGS = -I$(srcdir)/../../include $(ICU_CPPFLAGS)
 @HAVE_SCRIPT_FALSE@lib_LTLIBRARIES = libfstfar.la
 @HAVE_SCRIPT_TRUE@lib_LTLIBRARIES = libfstfar.la libfstfarscript.la
 libfstfar_la_SOURCES = sttable.cc stlist.cc
-libfstfar_la_LDFLAGS = -version-info 13:0:0
+libfstfar_la_LDFLAGS = -version-info 14:0:0
 libfstfar_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 @HAVE_SCRIPT_TRUE@libfstfarscript_la_SOURCES = far-class.cc farscript.cc getters.cc script-impl.cc \
 @HAVE_SCRIPT_TRUE@                             strings.cc
 
-@HAVE_SCRIPT_TRUE@libfstfarscript_la_LDFLAGS = -version-info 13:0:0
+@HAVE_SCRIPT_TRUE@libfstfarscript_la_LDFLAGS = -version-info 14:0:0
 @HAVE_SCRIPT_TRUE@libfstfarscript_la_LIBADD = \
 @HAVE_SCRIPT_TRUE@    libfstfar.la ../../script/libfstscript.la \
 @HAVE_SCRIPT_TRUE@        ../../lib/libfst.la -lm $(DL_LIBS)
index 438232c..e6ac495 100644 (file)
@@ -13,12 +13,8 @@ namespace script {
 // FarReaderClass.
 
 FarReaderClass *FarReaderClass::Open(const string &filename) {
-  OpenFarReaderClassArgs1 args(filename);
-  args.retval = nullptr;
-  Apply<Operation<OpenFarReaderClassArgs1>>("OpenFarReaderClass",
-                                            LoadArcTypeFromFar(filename),
-                                            &args);
-  return args.retval;
+  const std::vector<string> filenames{filename};
+  return FarReaderClass::Open(filenames);
 }
 
 FarReaderClass *FarReaderClass::Open(const std::vector<string> &filenames) {
@@ -28,20 +24,16 @@ FarReaderClass *FarReaderClass::Open(const std::vector<string> &filenames) {
   }
   const auto arc_type = LoadArcTypeFromFar(filenames.front());
   if (arc_type.empty()) return nullptr;
-  OpenFarReaderClassArgs2 args(filenames);
+  OpenFarReaderClassArgs args(filenames);
   args.retval = nullptr;
-  Apply<Operation<OpenFarReaderClassArgs2>>("OpenFarReaderClass", arc_type,
+  Apply<Operation<OpenFarReaderClassArgs>>("OpenFarReaderClass", arc_type,
                                             &args);
   return args.retval;
 }
 
-REGISTER_FST_OPERATION(OpenFarReaderClass, StdArc, OpenFarReaderClassArgs1);
-REGISTER_FST_OPERATION(OpenFarReaderClass, LogArc, OpenFarReaderClassArgs1);
-REGISTER_FST_OPERATION(OpenFarReaderClass, Log64Arc, OpenFarReaderClassArgs1);
-
-REGISTER_FST_OPERATION(OpenFarReaderClass, StdArc, OpenFarReaderClassArgs2);
-REGISTER_FST_OPERATION(OpenFarReaderClass, LogArc, OpenFarReaderClassArgs2);
-REGISTER_FST_OPERATION(OpenFarReaderClass, Log64Arc, OpenFarReaderClassArgs2);
+REGISTER_FST_OPERATION(OpenFarReaderClass, StdArc, OpenFarReaderClassArgs);
+REGISTER_FST_OPERATION(OpenFarReaderClass, LogArc, OpenFarReaderClassArgs);
+REGISTER_FST_OPERATION(OpenFarReaderClass, Log64Arc, OpenFarReaderClassArgs);
 
 // FarWriterClass.
 
index 5c5af5b..54f3dae 100644 (file)
@@ -13,7 +13,7 @@ endif
 
 if HAVE_SCRIPT
 libfstlinearscript_la_SOURCES = linearscript.cc
-libfstlinearscript_la_LDFLAGS = -version-info 13:0:0 -lm $(DL_LIBS)
+libfstlinearscript_la_LDFLAGS = -version-info 14:0:0 -lm $(DL_LIBS)
 libfstlinearscript_la_LIBADD = ../../script/libfstscript.la \
                                                        ../../lib/libfst.la -lm $(DL_LIBS)
 endif
index 2dbe5f3..3241703 100644 (file)
@@ -400,7 +400,7 @@ AM_CPPFLAGS = -I$(srcdir)/../../include $(ICU_CPPFLAGS)
 @HAVE_BIN_TRUE@fstlinear_SOURCES = fstlinear.cc
 @HAVE_BIN_TRUE@fstloglinearapply_SOURCES = fstloglinearapply.cc
 @HAVE_SCRIPT_TRUE@libfstlinearscript_la_SOURCES = linearscript.cc
-@HAVE_SCRIPT_TRUE@libfstlinearscript_la_LDFLAGS = -version-info 13:0:0 -lm $(DL_LIBS)
+@HAVE_SCRIPT_TRUE@libfstlinearscript_la_LDFLAGS = -version-info 14:0:0 -lm $(DL_LIBS)
 @HAVE_SCRIPT_TRUE@libfstlinearscript_la_LIBADD = ../../script/libfstscript.la \
 @HAVE_SCRIPT_TRUE@                                                     ../../lib/libfst.la -lm $(DL_LIBS)
 
index b0225a7..3aa369c 100644 (file)
@@ -8,7 +8,7 @@ lib_LTLIBRARIES = libfstlookahead.la
 
 libfstlookahead_la_SOURCES = arc_lookahead-fst.cc ilabel_lookahead-fst.cc \
                              olabel_lookahead-fst.cc
-libfstlookahead_la_LDFLAGS = -version-info 13:0:0
+libfstlookahead_la_LDFLAGS = -version-info 14:0:0
 libfstlookahead_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 
 arc_lookahead_fst_la_SOURCES = arc_lookahead-fst.cc
index 0e6bb31..5e4d5b7 100644 (file)
@@ -381,7 +381,7 @@ lib_LTLIBRARIES = libfstlookahead.la
 libfstlookahead_la_SOURCES = arc_lookahead-fst.cc ilabel_lookahead-fst.cc \
                              olabel_lookahead-fst.cc
 
-libfstlookahead_la_LDFLAGS = -version-info 13:0:0
+libfstlookahead_la_LDFLAGS = -version-info 14:0:0
 libfstlookahead_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 arc_lookahead_fst_la_SOURCES = arc_lookahead-fst.cc
 arc_lookahead_fst_la_LDFLAGS = -module
index bfcb5b3..da85805 100644 (file)
@@ -20,7 +20,7 @@ endif
 if HAVE_SCRIPT
 lib_LTLIBRARIES = libfstmpdtscript.la
 libfstmpdtscript_la_SOURCES = mpdtscript.cc
-libfstmpdtscript_la_LDFLAGS = -version-info 13:0:0
+libfstmpdtscript_la_LDFLAGS = -version-info 14:0:0
 libfstmpdtscript_la_LIBADD = ../../script/libfstscript.la \
                              ../../lib/libfst.la -lm $(DL_LIBS)
 endif
index 4798d1b..7bad13f 100644 (file)
@@ -398,7 +398,7 @@ AM_CPPFLAGS = -I$(srcdir)/../../include $(ICU_CPPFLAGS)
 @HAVE_BIN_TRUE@mpdtreverse_SOURCES = mpdtreverse.cc
 @HAVE_SCRIPT_TRUE@lib_LTLIBRARIES = libfstmpdtscript.la
 @HAVE_SCRIPT_TRUE@libfstmpdtscript_la_SOURCES = mpdtscript.cc
-@HAVE_SCRIPT_TRUE@libfstmpdtscript_la_LDFLAGS = -version-info 13:0:0
+@HAVE_SCRIPT_TRUE@libfstmpdtscript_la_LDFLAGS = -version-info 14:0:0
 @HAVE_SCRIPT_TRUE@libfstmpdtscript_la_LIBADD = ../../script/libfstscript.la \
 @HAVE_SCRIPT_TRUE@                             ../../lib/libfst.la -lm $(DL_LIBS)
 
index 7a15325..8a83721 100644 (file)
@@ -9,5 +9,5 @@ ngram_fst_la_SOURCES = bitmap-index.cc ngram-fst.cc nthbit.cc
 ngram_fst_la_LDFLAGS = -module
 
 libfstngram_la_SOURCES = bitmap-index.cc ngram-fst.cc nthbit.cc
-libfstngram_la_LDFLAGS = -version-info 13:0:0
+libfstngram_la_LDFLAGS = -version-info 14:0:0
 libfstngram_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
index e0bec14..67812c6 100644 (file)
@@ -355,7 +355,7 @@ lib_LTLIBRARIES = libfstngram.la
 ngram_fst_la_SOURCES = bitmap-index.cc ngram-fst.cc nthbit.cc
 ngram_fst_la_LDFLAGS = -module
 libfstngram_la_SOURCES = bitmap-index.cc ngram-fst.cc nthbit.cc
-libfstngram_la_LDFLAGS = -version-info 13:0:0
+libfstngram_la_LDFLAGS = -version-info 14:0:0
 libfstngram_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 all: all-am
 
index cbaf8aa..6f2499e 100644 (file)
@@ -24,7 +24,7 @@ endif
 if HAVE_SCRIPT
 lib_LTLIBRARIES = libfstpdtscript.la
 libfstpdtscript_la_SOURCES = getters.cc pdtscript.cc
-libfstpdtscript_la_LDFLAGS = -version-info 13:0:0
+libfstpdtscript_la_LDFLAGS = -version-info 14:0:0
 libfstpdtscript_la_LIBADD = ../../script/libfstscript.la \
                             ../../lib/libfst.la -lm $(DL_LIBS)
 endif
index ef567c6..215a50b 100644 (file)
@@ -413,7 +413,7 @@ AM_CPPFLAGS = -I$(srcdir)/../../include $(ICU_CPPFLAGS)
 @HAVE_BIN_TRUE@pdtshortestpath_SOURCES = pdtshortestpath.cc
 @HAVE_SCRIPT_TRUE@lib_LTLIBRARIES = libfstpdtscript.la
 @HAVE_SCRIPT_TRUE@libfstpdtscript_la_SOURCES = getters.cc pdtscript.cc
-@HAVE_SCRIPT_TRUE@libfstpdtscript_la_LDFLAGS = -version-info 13:0:0
+@HAVE_SCRIPT_TRUE@libfstpdtscript_la_LDFLAGS = -version-info 14:0:0
 @HAVE_SCRIPT_TRUE@libfstpdtscript_la_LIBADD = ../../script/libfstscript.la \
 @HAVE_SCRIPT_TRUE@                            ../../lib/libfst.la -lm $(DL_LIBS)
 
index 45c15c5..7d8e379 100644 (file)
@@ -108,6 +108,7 @@ cdef extern from "<fst/fstlib.h>" namespace "fst" nogil:
   const int kNoStateId
   const int64 kNoSymbol
 
+
   enum ClosureType:
     CLOSURE_STAR
     CLOSURE_PLUS
@@ -186,6 +187,9 @@ cdef extern from "<fst/fstlib.h>" namespace "fst" nogil:
   # Symbol tables.
   cdef cppclass SymbolTable:
 
+    @staticmethod
+    int64 kNoSymbol
+
     SymbolTable()
 
     SymbolTable(const string &)
@@ -193,6 +197,10 @@ cdef extern from "<fst/fstlib.h>" namespace "fst" nogil:
     @staticmethod
     SymbolTable *Read(const string &)
 
+    # Aliased for overload.
+    @staticmethod
+    SymbolTable *ReadStream "Read"(istream &, const string &)
+
     @staticmethod
     SymbolTable *ReadText(const string &, const SymbolTableTextOptions &)
 
@@ -226,8 +234,16 @@ cdef extern from "<fst/fstlib.h>" namespace "fst" nogil:
 
     const string &LabeledCheckSum()
 
+    bool Write(ostream &)
+
     bool Write(const string &)
 
+    bool WriteToString(ostream &)
+
+    bool WriteToString(const string &)
+
+    bool WriteText(ostream &)
+
     bool WriteText(const string &)
 
     int64 AvailableKey()
@@ -322,7 +338,7 @@ cdef extern from "<fst/script/fstscript.h>" namespace "fst::script" nogil:
 
     # Aliased for overload.
     @staticmethod
-    FstClass *ReadFromStream "Read"(istream &, const string &)
+    FstClass *ReadStream "Read"(istream &, const string &)
 
     int64 Start()
 
index ab09be1..d6b8262 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by Cython 0.28.3 */
+/* Generated by Cython 0.29 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
@@ -7,8 +7,9 @@
 #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
     #error Cython requires Python 2.6+ or Python 3.3+.
 #else
-#define CYTHON_ABI "0_28_3"
-#define CYTHON_FUTURE_DIVISION 0
+#define CYTHON_ABI "0_29"
+#define CYTHON_HEX_VERSION 0x001D00F0
+#define CYTHON_FUTURE_DIVISION 1
 #include <stddef.h>
 #ifndef offsetof
   #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
   #define CYTHON_PEP489_MULTI_PHASE_INIT 0
   #undef CYTHON_USE_TP_FINALIZE
   #define CYTHON_USE_TP_FINALIZE 0
+  #undef CYTHON_USE_DICT_VERSIONS
+  #define CYTHON_USE_DICT_VERSIONS 0
+  #undef CYTHON_USE_EXC_INFO_STACK
+  #define CYTHON_USE_EXC_INFO_STACK 0
 #elif defined(PYSTON_VERSION)
   #define CYTHON_COMPILING_IN_PYPY 0
   #define CYTHON_COMPILING_IN_PYSTON 1
   #define CYTHON_PEP489_MULTI_PHASE_INIT 0
   #undef CYTHON_USE_TP_FINALIZE
   #define CYTHON_USE_TP_FINALIZE 0
+  #undef CYTHON_USE_DICT_VERSIONS
+  #define CYTHON_USE_DICT_VERSIONS 0
+  #undef CYTHON_USE_EXC_INFO_STACK
+  #define CYTHON_USE_EXC_INFO_STACK 0
 #else
   #define CYTHON_COMPILING_IN_PYPY 0
   #define CYTHON_COMPILING_IN_PYSTON 0
     #define CYTHON_FAST_PYCALL 1
   #endif
   #ifndef CYTHON_PEP489_MULTI_PHASE_INIT
-    #define CYTHON_PEP489_MULTI_PHASE_INIT (0 && PY_VERSION_HEX >= 0x03050000)
+    #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000)
   #endif
   #ifndef CYTHON_USE_TP_FINALIZE
     #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1)
   #endif
+  #ifndef CYTHON_USE_DICT_VERSIONS
+    #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1)
+  #endif
+  #ifndef CYTHON_USE_EXC_INFO_STACK
+    #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3)
+  #endif
 #endif
 #if !defined(CYTHON_FAST_PYCCALL)
 #define CYTHON_FAST_PYCCALL  (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1)
@@ -322,6 +337,9 @@ class __Pyx_FakeReference {
 #ifndef Py_TPFLAGS_HAVE_FINALIZE
   #define Py_TPFLAGS_HAVE_FINALIZE 0
 #endif
+#ifndef METH_STACKLESS
+  #define METH_STACKLESS 0
+#endif
 #if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL)
   #ifndef METH_FASTCALL
      #define METH_FASTCALL 0x80
@@ -335,15 +353,40 @@ class __Pyx_FakeReference {
 #endif
 #if CYTHON_FAST_PYCCALL
 #define __Pyx_PyFastCFunction_Check(func)\
-    ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS)))))
+    ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS)))))
 #else
 #define __Pyx_PyFastCFunction_Check(func) 0
 #endif
+#if CYTHON_USE_DICT_VERSIONS
+#define __PYX_GET_DICT_VERSION(dict)  (((PyDictObject*)(dict))->ma_version_tag)
+#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\
+    (version_var) = __PYX_GET_DICT_VERSION(dict);\
+    (cache_var) = (value);
+#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\
+        static PY_UINT64_T __pyx_dict_version = 0;\
+        static PyObject *__pyx_dict_cached_value = NULL;\
+        if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\
+            (VAR) = __pyx_dict_cached_value;\
+        } else {\
+            (VAR) = __pyx_dict_cached_value = (LOOKUP);\
+            __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\
+        }\
+    }
+#else
+#define __PYX_GET_DICT_VERSION(dict)  (0)
+#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)
+#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP)  (VAR) = (LOOKUP);
+#endif
 #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc)
   #define PyObject_Malloc(s)   PyMem_Malloc(s)
   #define PyObject_Free(p)     PyMem_Free(p)
   #define PyObject_Realloc(p)  PyMem_Realloc(p)
 #endif
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1
+  #define PyMem_RawMalloc(n)           PyMem_Malloc(n)
+  #define PyMem_RawRealloc(p, n)       PyMem_Realloc(p, n)
+  #define PyMem_RawFree(p)             PyMem_Free(p)
+#endif
 #if CYTHON_COMPILING_IN_PYSTON
   #define __Pyx_PyCode_HasFreeVars(co)  PyCode_HasFreeVars(co)
   #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno)
@@ -451,8 +494,8 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
 #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format)
   #define PyObject_Format(obj, fmt)  PyObject_CallMethod(obj, "__format__", "O", fmt)
 #endif
-#define __Pyx_PyString_FormatSafe(a, b)   ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b))
-#define __Pyx_PyUnicode_FormatSafe(a, b)  ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
+#define __Pyx_PyString_FormatSafe(a, b)   ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b))
+#define __Pyx_PyUnicode_FormatSafe(a, b)  ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
 #if PY_MAJOR_VERSION >= 3
   #define __Pyx_PyString_Format(a, b)  PyUnicode_Format(a, b)
 #else
@@ -613,9 +656,9 @@ typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* enc
 
 #define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
 #define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0
-#define __PYX_DEFAULT_STRING_ENCODING ""
-#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
-#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
+#define __PYX_DEFAULT_STRING_ENCODING "utf8"
+#define __Pyx_PyObject_FromString __Pyx_PyUnicode_FromString
+#define __Pyx_PyObject_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize
 #define __Pyx_uchar_cast(c) ((unsigned char)c)
 #define __Pyx_long_cast(x) ((long)x)
 #define __Pyx_fits_Py_ssize_t(v, type, is_signed)  (\
@@ -628,6 +671,9 @@ typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* enc
     (sizeof(type) == sizeof(Py_ssize_t) &&\
           (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\
                                v == (type)PY_SSIZE_T_MAX)))  )
+static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) {
+    return (size_t) i < (size_t) limit;
+}
 #if defined (__cplusplus) && __cplusplus >= 201103L
     #include <cstdlib>
     #define __Pyx_sst_abs(value) std::abs(value)
@@ -686,6 +732,7 @@ static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) {
 #define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None)
 static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b);
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
+static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*);
 static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x);
 #define __Pyx_PySequence_Tuple(obj)\
     (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj))
@@ -766,7 +813,7 @@ static int __Pyx_init_sys_getdefaultencoding_params(void) {
     if (!default_encoding) goto bad;
     default_encoding_c = PyBytes_AsString(default_encoding);
     if (!default_encoding_c) goto bad;
-    __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c));
+    __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1);
     if (!__PYX_DEFAULT_STRING_ENCODING) goto bad;
     strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c);
     Py_DECREF(default_encoding);
@@ -896,7 +943,7 @@ struct __pyx_obj_9pywrapfst_Compiler;
 struct __pyx_obj_9pywrapfst_FarReader;
 struct __pyx_obj_9pywrapfst_FarWriter;
 
-/* "fst.pxd":496
+/* "fst.pxd":512
  * 
  * 
  * ctypedef pair[int64, const FstClass *] LabelFstClassPair             # <<<<<<<<<<<<<<
@@ -905,7 +952,7 @@ struct __pyx_obj_9pywrapfst_FarWriter;
  */
 typedef std::pair<__pyx_t_10basictypes_int64,fst::script::FstClass const *>  __pyx_t_3fst_LabelFstClassPair;
 
-/* "fst.pxd":498
+/* "fst.pxd":514
  * ctypedef pair[int64, const FstClass *] LabelFstClassPair
  * 
  * ctypedef pair[int64, int64] LabelPair             # <<<<<<<<<<<<<<
@@ -953,7 +1000,7 @@ struct __pyx_opt_args_9pywrapfst_reverse;
 struct __pyx_opt_args_9pywrapfst__shortestdistance;
 struct __pyx_opt_args_9pywrapfst_shortestpath;
 
-/* "pywrapfst.pxd":41
+/* "pywrapfst.pxd":40
  * 
  * 
  * cdef string tostring(data, encoding=?) except *             # <<<<<<<<<<<<<<
@@ -965,7 +1012,7 @@ struct __pyx_opt_args_9pywrapfst_tostring {
   PyObject *encoding;
 };
 
-/* "pywrapfst.pxd":43
+/* "pywrapfst.pxd":42
  * cdef string tostring(data, encoding=?) except *
  * 
  * cdef string weight_tostring(data, encoding=?) except *             # <<<<<<<<<<<<<<
@@ -977,7 +1024,7 @@ struct __pyx_opt_args_9pywrapfst_weight_tostring {
   PyObject *encoding;
 };
 
-/* "pywrapfst.pxd":99
+/* "pywrapfst.pxd":98
  * # SymbolTable.
  * 
  * ctypedef fst.SymbolTable * SymbolTable_ptr             # <<<<<<<<<<<<<<
@@ -986,7 +1033,7 @@ struct __pyx_opt_args_9pywrapfst_weight_tostring {
  */
 typedef fst::SymbolTable *__pyx_t_9pywrapfst_SymbolTable_ptr;
 
-/* "pywrapfst.pxd":139
+/* "pywrapfst.pxd":140
  * cdef class _MutableSymbolTable(_SymbolTable):
  * 
  *   cpdef int64 add_symbol(self, symbol, int64 key=?)             # <<<<<<<<<<<<<<
@@ -998,7 +1045,7 @@ struct __pyx_opt_args_9pywrapfst_19_MutableSymbolTable_add_symbol {
   __pyx_t_10basictypes_int64 key;
 };
 
-/* "pywrapfst.pxd":215
+/* "pywrapfst.pxd":218
  * 
  * 
  * ctypedef fst.FstClass * FstClass_ptr             # <<<<<<<<<<<<<<
@@ -1007,7 +1054,7 @@ struct __pyx_opt_args_9pywrapfst_19_MutableSymbolTable_add_symbol {
  */
 typedef fst::script::FstClass *__pyx_t_9pywrapfst_FstClass_ptr;
 
-/* "pywrapfst.pxd":216
+/* "pywrapfst.pxd":219
  * 
  * ctypedef fst.FstClass * FstClass_ptr
  * ctypedef fst.MutableFstClass * MutableFstClass_ptr             # <<<<<<<<<<<<<<
@@ -1016,7 +1063,7 @@ typedef fst::script::FstClass *__pyx_t_9pywrapfst_FstClass_ptr;
  */
 typedef fst::script::MutableFstClass *__pyx_t_9pywrapfst_MutableFstClass_ptr;
 
-/* "pywrapfst.pxd":217
+/* "pywrapfst.pxd":220
  * ctypedef fst.FstClass * FstClass_ptr
  * ctypedef fst.MutableFstClass * MutableFstClass_ptr
  * ctypedef fst.VectorFstClass * VectorFstClass_ptr             # <<<<<<<<<<<<<<
@@ -1025,7 +1072,7 @@ typedef fst::script::MutableFstClass *__pyx_t_9pywrapfst_MutableFstClass_ptr;
  */
 typedef fst::script::VectorFstClass *__pyx_t_9pywrapfst_VectorFstClass_ptr;
 
-/* "pywrapfst.pxd":230
+/* "pywrapfst.pxd":236
  *   cpdef _Fst copy(self)
  * 
  *   cpdef void draw(self, filename, _SymbolTable isymbols=?,             # <<<<<<<<<<<<<<
@@ -1051,7 +1098,7 @@ struct __pyx_opt_args_9pywrapfst_4_Fst_draw {
   bool show_weight_one;
 };
 
-/* "pywrapfst.pxd":258
+/* "pywrapfst.pxd":264
  *   cpdef StateIterator states(self)
  * 
  *   cpdef string text(self, _SymbolTable isymbols=?, _SymbolTable osymbols=?,             # <<<<<<<<<<<<<<
@@ -1068,7 +1115,7 @@ struct __pyx_opt_args_9pywrapfst_4_Fst_text {
   PyObject *missing_sym;
 };
 
-/* "pywrapfst.pxd":281
+/* "pywrapfst.pxd":287
  *   cpdef int64 add_state(self) except *
  * 
  *   cdef void _arcsort(self, sort_type=?) except *             # <<<<<<<<<<<<<<
@@ -1080,7 +1127,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__arcsort {
   PyObject *sort_type;
 };
 
-/* "pywrapfst.pxd":283
+/* "pywrapfst.pxd":289
  *   cdef void _arcsort(self, sort_type=?) except *
  * 
  *   cdef void _closure(self, bool closure_plus=?) except *             # <<<<<<<<<<<<<<
@@ -1092,7 +1139,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__closure {
   bool closure_plus;
 };
 
-/* "pywrapfst.pxd":291
+/* "pywrapfst.pxd":297
  *   cdef void _decode(self, EncodeMapper) except *
  * 
  *   cdef void _delete_arcs(self, int64 state, size_t n=?) except *             # <<<<<<<<<<<<<<
@@ -1104,7 +1151,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__delete_arcs {
   size_t n;
 };
 
-/* "pywrapfst.pxd":293
+/* "pywrapfst.pxd":299
  *   cdef void _delete_arcs(self, int64 state, size_t n=?) except *
  * 
  *   cdef void _delete_states(self, states=?) except *             # <<<<<<<<<<<<<<
@@ -1116,7 +1163,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__delete_states {
   PyObject *states;
 };
 
-/* "pywrapfst.pxd":299
+/* "pywrapfst.pxd":305
  *   cdef void _invert(self) except *
  * 
  *   cdef void _minimize(self, float delta=?, bool allow_nondet=?) except *             # <<<<<<<<<<<<<<
@@ -1129,7 +1176,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__minimize {
   bool allow_nondet;
 };
 
-/* "pywrapfst.pxd":305
+/* "pywrapfst.pxd":311
  *   cpdef int64 num_states(self)
  * 
  *   cdef void _project(self, bool project_output=?) except *             # <<<<<<<<<<<<<<
@@ -1141,7 +1188,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__project {
   bool project_output;
 };
 
-/* "pywrapfst.pxd":307
+/* "pywrapfst.pxd":313
  *   cdef void _project(self, bool project_output=?) except *
  * 
  *   cdef void _prune(self, float delta=?, int64 nstate=?, weight=?) except *             # <<<<<<<<<<<<<<
@@ -1155,7 +1202,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__prune {
   PyObject *weight;
 };
 
-/* "pywrapfst.pxd":309
+/* "pywrapfst.pxd":315
  *   cdef void _prune(self, float delta=?, int64 nstate=?, weight=?) except *
  * 
  *   cdef void _push(self, float delta=?, bool remove_total_weight=?,             # <<<<<<<<<<<<<<
@@ -1169,7 +1216,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__push {
   bool to_final;
 };
 
-/* "pywrapfst.pxd":312
+/* "pywrapfst.pxd":318
  *                   bool to_final=?) except *
  * 
  *   cdef void _relabel_pairs(self, ipairs=?, opairs=?) except *             # <<<<<<<<<<<<<<
@@ -1182,7 +1229,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__relabel_pairs {
   PyObject *opairs;
 };
 
-/* "pywrapfst.pxd":314
+/* "pywrapfst.pxd":320
  *   cdef void _relabel_pairs(self, ipairs=?, opairs=?) except *
  * 
  *   cdef void _relabel_tables(self, _SymbolTable old_isymbols=?,             # <<<<<<<<<<<<<<
@@ -1201,7 +1248,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__relabel_tables {
   bool attach_new_osymbols;
 };
 
-/* "pywrapfst.pxd":324
+/* "pywrapfst.pxd":330
  *   cdef void _reserve_states(self, int64 n) except *
  * 
  *   cdef void _reweight(self, potentials, bool to_final=?) except *             # <<<<<<<<<<<<<<
@@ -1213,7 +1260,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__reweight {
   bool to_final;
 };
 
-/* "pywrapfst.pxd":326
+/* "pywrapfst.pxd":332
  *   cdef void _reweight(self, potentials, bool to_final=?) except *
  * 
  *   cdef void _rmepsilon(self, queue_type=?, bool connect=?, weight=?,             # <<<<<<<<<<<<<<
@@ -1229,7 +1276,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__rmepsilon {
   float delta;
 };
 
-/* "pywrapfst.pxd":329
+/* "pywrapfst.pxd":335
  *                        int64 nstate=?, float delta=?) except *
  * 
  *   cdef void _set_final(self, int64 state, weight=?) except *             # <<<<<<<<<<<<<<
@@ -1241,7 +1288,7 @@ struct __pyx_opt_args_9pywrapfst_11_MutableFst__set_final {
   PyObject *weight;
 };
 
-/* "pywrapfst.pxd":353
+/* "pywrapfst.pxd":359
  * cdef _Fst _init_XFst(FstClass_ptr tfst)
  * 
  * cdef _MutableFst _create_Fst(arc_type=?)             # <<<<<<<<<<<<<<
@@ -1253,12 +1300,12 @@ struct __pyx_opt_args_9pywrapfst__create_Fst {
   PyObject *arc_type;
 };
 
-/* "pywrapfst.pxd":436
+/* "pywrapfst.pxd":442
  * 
  * 
  * cdef _Fst _map(_Fst ifst, float delta=?, map_type=?, double power=?, weight=?)             # <<<<<<<<<<<<<<
  * 
- * cpdef _Fst arcmap(_Fst ifst, float delta=?, map_type=?, double power=?, weight=?)
+ * cpdef _Fst arcmap(_Fst ifst, float delta=?, map_type=?, double power=?,
  */
 struct __pyx_opt_args_9pywrapfst__map {
   int __pyx_n;
@@ -1268,12 +1315,12 @@ struct __pyx_opt_args_9pywrapfst__map {
   PyObject *weight;
 };
 
-/* "pywrapfst.pxd":438
+/* "pywrapfst.pxd":444
  * cdef _Fst _map(_Fst ifst, float delta=?, map_type=?, double power=?, weight=?)
  * 
- * cpdef _Fst arcmap(_Fst ifst, float delta=?, map_type=?, double power=?, weight=?)             # <<<<<<<<<<<<<<
+ * cpdef _Fst arcmap(_Fst ifst, float delta=?, map_type=?, double power=?,             # <<<<<<<<<<<<<<
+ *                   weight=?)
  * 
- * cpdef _MutableFst compose(_Fst ifst1, _Fst ifst2, compose_filter=?,
  */
 struct __pyx_opt_args_9pywrapfst_arcmap {
   int __pyx_n;
@@ -1283,8 +1330,8 @@ struct __pyx_opt_args_9pywrapfst_arcmap {
   PyObject *weight;
 };
 
-/* "pywrapfst.pxd":440
- * cpdef _Fst arcmap(_Fst ifst, float delta=?, map_type=?, double power=?, weight=?)
+/* "pywrapfst.pxd":447
+ *                   weight=?)
  * 
  * cpdef _MutableFst compose(_Fst ifst1, _Fst ifst2, compose_filter=?,             # <<<<<<<<<<<<<<
  *                           bool connect=?)
@@ -1296,7 +1343,7 @@ struct __pyx_opt_args_9pywrapfst_compose {
   bool connect;
 };
 
-/* "pywrapfst.pxd":443
+/* "pywrapfst.pxd":450
  *                           bool connect=?)
  * 
  * cpdef _Fst convert(_Fst ifst, fst_type=?)             # <<<<<<<<<<<<<<
@@ -1308,7 +1355,7 @@ struct __pyx_opt_args_9pywrapfst_convert {
   PyObject *fst_type;
 };
 
-/* "pywrapfst.pxd":445
+/* "pywrapfst.pxd":452
  * cpdef _Fst convert(_Fst ifst, fst_type=?)
  * 
  * cpdef _MutableFst determinize(_Fst ifst, float delta=?, det_type=?,             # <<<<<<<<<<<<<<
@@ -1325,7 +1372,7 @@ struct __pyx_opt_args_9pywrapfst_determinize {
   bool increment_subsequential_label;
 };
 
-/* "pywrapfst.pxd":449
+/* "pywrapfst.pxd":456
  *                               weight=?, bool increment_subsequential_label=?)
  * 
  * cpdef _MutableFst difference(_Fst ifst1, _Fst ifst2, compose_filter=?,             # <<<<<<<<<<<<<<
@@ -1338,7 +1385,7 @@ struct __pyx_opt_args_9pywrapfst_difference {
   bool connect;
 };
 
-/* "pywrapfst.pxd":452
+/* "pywrapfst.pxd":459
  *                              bool connect=?)
  * 
  * cpdef _MutableFst disambiguate(_Fst ifst, float delta=?, int64 nstate=?,             # <<<<<<<<<<<<<<
@@ -1353,7 +1400,7 @@ struct __pyx_opt_args_9pywrapfst_disambiguate {
   PyObject *weight;
 };
 
-/* "pywrapfst.pxd":455
+/* "pywrapfst.pxd":462
  *                                int64 subsequential_label=?, weight=?)
  * 
  * cpdef _MutableFst epsnormalize(_Fst ifst, bool eps_norm_output=?)             # <<<<<<<<<<<<<<
@@ -1365,7 +1412,7 @@ struct __pyx_opt_args_9pywrapfst_epsnormalize {
   bool eps_norm_output;
 };
 
-/* "pywrapfst.pxd":457
+/* "pywrapfst.pxd":464
  * cpdef _MutableFst epsnormalize(_Fst ifst, bool eps_norm_output=?)
  * 
  * cpdef bool equal(_Fst ifst1, _Fst ifst2, float delta=?)             # <<<<<<<<<<<<<<
@@ -1377,7 +1424,7 @@ struct __pyx_opt_args_9pywrapfst_equal {
   float delta;
 };
 
-/* "pywrapfst.pxd":459
+/* "pywrapfst.pxd":466
  * cpdef bool equal(_Fst ifst1, _Fst ifst2, float delta=?)
  * 
  * cpdef bool equivalent(_Fst ifst1, _Fst ifst2, float delta=?) except *             # <<<<<<<<<<<<<<
@@ -1389,7 +1436,7 @@ struct __pyx_opt_args_9pywrapfst_equivalent {
   float delta;
 };
 
-/* "pywrapfst.pxd":461
+/* "pywrapfst.pxd":468
  * cpdef bool equivalent(_Fst ifst1, _Fst ifst2, float delta=?) except *
  * 
  * cpdef _MutableFst intersect(_Fst ifst1, _Fst ifst2, compose_filter=?,             # <<<<<<<<<<<<<<
@@ -1402,7 +1449,7 @@ struct __pyx_opt_args_9pywrapfst_intersect {
   bool connect;
 };
 
-/* "pywrapfst.pxd":464
+/* "pywrapfst.pxd":471
  *                             bool connect=?)
  * 
  * cpdef bool isomorphic(_Fst ifst1, _Fst ifst2, float delta=?)             # <<<<<<<<<<<<<<
@@ -1414,7 +1461,7 @@ struct __pyx_opt_args_9pywrapfst_isomorphic {
   float delta;
 };
 
-/* "pywrapfst.pxd":466
+/* "pywrapfst.pxd":473
  * cpdef bool isomorphic(_Fst ifst1, _Fst ifst2, float delta=?)
  * 
  * cpdef _MutableFst prune(_Fst ifst, float delta=?, int64 nstate=?,             # <<<<<<<<<<<<<<
@@ -1428,7 +1475,7 @@ struct __pyx_opt_args_9pywrapfst_prune {
   PyObject *weight;
 };
 
-/* "pywrapfst.pxd":469
+/* "pywrapfst.pxd":476
  *                         weight=?)
  * 
  * cpdef _MutableFst push(_Fst ifst, float delta=?, bool push_weights=?,             # <<<<<<<<<<<<<<
@@ -1445,7 +1492,7 @@ struct __pyx_opt_args_9pywrapfst_push {
   bool to_final;
 };
 
-/* "pywrapfst.pxd":473
+/* "pywrapfst.pxd":480
  *                        bool remove_total_weight=?, bool to_final=?)
  * 
  * cpdef bool randequivalent(_Fst ifst1, _Fst ifst2, int32 npath=?,             # <<<<<<<<<<<<<<
@@ -1461,7 +1508,7 @@ struct __pyx_opt_args_9pywrapfst_randequivalent {
   __pyx_t_10basictypes_int32 max_length;
 };
 
-/* "pywrapfst.pxd":477
+/* "pywrapfst.pxd":484
  *                           int32 max_length=?) except *
  * 
  * cpdef _MutableFst randgen(_Fst ifst, int32 npath=?, time_t seed=?,             # <<<<<<<<<<<<<<
@@ -1478,7 +1525,7 @@ struct __pyx_opt_args_9pywrapfst_randgen {
   bool weighted;
 };
 
-/* "pywrapfst.pxd":484
+/* "pywrapfst.pxd":491
  *     bool epsilon_on_replace) except *
  * 
  * cpdef _MutableFst replace(pairs, call_arc_labeling=?, return_arc_labeling=?,             # <<<<<<<<<<<<<<
@@ -1493,7 +1540,7 @@ struct __pyx_opt_args_9pywrapfst_replace {
   __pyx_t_10basictypes_int64 return_label;
 };
 
-/* "pywrapfst.pxd":487
+/* "pywrapfst.pxd":494
  *                           bool epsilon_on_replace=?, int64 return_label=?)
  * 
  * cpdef _MutableFst reverse(_Fst ifst, bool require_superinitial=?)             # <<<<<<<<<<<<<<
@@ -1505,7 +1552,7 @@ struct __pyx_opt_args_9pywrapfst_reverse {
   bool require_superinitial;
 };
 
-/* "pywrapfst.pxd":489
+/* "pywrapfst.pxd":496
  * cpdef _MutableFst reverse(_Fst ifst, bool require_superinitial=?)
  * 
  * cdef vector[fst.WeightClass] *_shortestdistance(_Fst ifst, float delta=?,             # <<<<<<<<<<<<<<
@@ -1520,7 +1567,7 @@ struct __pyx_opt_args_9pywrapfst__shortestdistance {
   bool reverse;
 };
 
-/* "pywrapfst.pxd":493
+/* "pywrapfst.pxd":500
  *                                                 bool reverse=?) except *
  * 
  * cpdef _MutableFst shortestpath(_Fst ifst, float delta=?, int32 nshortest=?,             # <<<<<<<<<<<<<<
@@ -1537,7 +1584,7 @@ struct __pyx_opt_args_9pywrapfst_shortestpath {
   PyObject *weight;
 };
 
-/* "pywrapfst.pxd":69
+/* "pywrapfst.pxd":68
  * 
  * 
  * cdef class Weight(object):             # <<<<<<<<<<<<<<
@@ -1551,7 +1598,7 @@ struct __pyx_obj_9pywrapfst_Weight {
 };
 
 
-/* "pywrapfst.pxd":102
+/* "pywrapfst.pxd":101
  * 
  * 
  * cdef class _SymbolTable(object):             # <<<<<<<<<<<<<<
@@ -1565,7 +1612,7 @@ struct __pyx_obj_9pywrapfst__SymbolTable {
 };
 
 
-/* "pywrapfst.pxd":127
+/* "pywrapfst.pxd":128
  * 
  * 
  * cdef class _EncodeMapperSymbolTable(_SymbolTable):             # <<<<<<<<<<<<<<
@@ -1578,7 +1625,7 @@ struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable {
 };
 
 
-/* "pywrapfst.pxd":132
+/* "pywrapfst.pxd":133
  * 
  * 
  * cdef class _FstSymbolTable(_SymbolTable):             # <<<<<<<<<<<<<<
@@ -1591,7 +1638,7 @@ struct __pyx_obj_9pywrapfst__FstSymbolTable {
 };
 
 
-/* "pywrapfst.pxd":137
+/* "pywrapfst.pxd":138
  * 
  * 
  * cdef class _MutableSymbolTable(_SymbolTable):             # <<<<<<<<<<<<<<
@@ -1603,7 +1650,7 @@ struct __pyx_obj_9pywrapfst__MutableSymbolTable {
 };
 
 
-/* "pywrapfst.pxd":146
+/* "pywrapfst.pxd":147
  * 
  * 
  * cdef class _MutableFstSymbolTable(_MutableSymbolTable):             # <<<<<<<<<<<<<<
@@ -1616,7 +1663,7 @@ struct __pyx_obj_9pywrapfst__MutableFstSymbolTable {
 };
 
 
-/* "pywrapfst.pxd":151
+/* "pywrapfst.pxd":152
  * 
  * 
  * cdef class SymbolTable(_MutableSymbolTable):             # <<<<<<<<<<<<<<
@@ -1629,7 +1676,7 @@ struct __pyx_obj_9pywrapfst_SymbolTable {
 };
 
 
-/* "pywrapfst.pxd":172
+/* "pywrapfst.pxd":175
  * 
  * 
  * cdef class SymbolTableIterator(object):             # <<<<<<<<<<<<<<
@@ -1644,7 +1691,7 @@ struct __pyx_obj_9pywrapfst_SymbolTableIterator {
 };
 
 
-/* "pywrapfst.pxd":191
+/* "pywrapfst.pxd":194
  * 
  * 
  * cdef class EncodeMapper(object):             # <<<<<<<<<<<<<<
@@ -1658,7 +1705,7 @@ struct __pyx_obj_9pywrapfst_EncodeMapper {
 };
 
 
-/* "pywrapfst.pxd":220
+/* "pywrapfst.pxd":223
  * 
  * 
  * cdef class _Fst(object):             # <<<<<<<<<<<<<<
@@ -1672,7 +1719,7 @@ struct __pyx_obj_9pywrapfst__Fst {
 };
 
 
-/* "pywrapfst.pxd":271
+/* "pywrapfst.pxd":277
  * 
  * 
  * cdef class _MutableFst(_Fst):             # <<<<<<<<<<<<<<
@@ -1685,7 +1732,7 @@ struct __pyx_obj_9pywrapfst__MutableFst {
 };
 
 
-/* "pywrapfst.pxd":363
+/* "pywrapfst.pxd":369
  * 
  * 
  * cdef class Arc(object):             # <<<<<<<<<<<<<<
@@ -1699,7 +1746,7 @@ struct __pyx_obj_9pywrapfst_Arc {
 };
 
 
-/* "pywrapfst.pxd":373
+/* "pywrapfst.pxd":379
  * 
  * 
  * cdef class ArcIterator(object):             # <<<<<<<<<<<<<<
@@ -1714,7 +1761,7 @@ struct __pyx_obj_9pywrapfst_ArcIterator {
 };
 
 
-/* "pywrapfst.pxd":395
+/* "pywrapfst.pxd":401
  * 
  * 
  * cdef class MutableArcIterator(object):             # <<<<<<<<<<<<<<
@@ -1729,7 +1776,7 @@ struct __pyx_obj_9pywrapfst_MutableArcIterator {
 };
 
 
-/* "pywrapfst.pxd":419
+/* "pywrapfst.pxd":425
  * 
  * 
  * cdef class StateIterator(object):             # <<<<<<<<<<<<<<
@@ -1744,7 +1791,7 @@ struct __pyx_obj_9pywrapfst_StateIterator {
 };
 
 
-/* "pywrapfst.pxd":505
+/* "pywrapfst.pxd":512
  * 
  * 
  * cdef class Compiler(object):             # <<<<<<<<<<<<<<
@@ -1768,7 +1815,7 @@ struct __pyx_obj_9pywrapfst_Compiler {
 };
 
 
-/* "pywrapfst.pxd":526
+/* "pywrapfst.pxd":533
  * # FarReader.
  * 
  * cdef class FarReader(object):             # <<<<<<<<<<<<<<
@@ -1782,7 +1829,7 @@ struct __pyx_obj_9pywrapfst_FarReader {
 };
 
 
-/* "pywrapfst.pxd":551
+/* "pywrapfst.pxd":558
  * # FarWriter.
  * 
  * cdef class FarWriter(object):             # <<<<<<<<<<<<<<
@@ -1797,7 +1844,7 @@ struct __pyx_obj_9pywrapfst_FarWriter {
 
 
 
-/* "pywrapfst.pyx":348
+/* "pywrapfst.pyx":333
  * 
  * 
  * cdef class Weight(object):             # <<<<<<<<<<<<<<
@@ -1814,7 +1861,7 @@ struct __pyx_vtabstruct_9pywrapfst_Weight {
 static struct __pyx_vtabstruct_9pywrapfst_Weight *__pyx_vtabptr_9pywrapfst_Weight;
 
 
-/* "pywrapfst.pyx":675
+/* "pywrapfst.pyx":660
  * 
  * 
  * cdef class _SymbolTable(object):             # <<<<<<<<<<<<<<
@@ -1824,20 +1871,21 @@ static struct __pyx_vtabstruct_9pywrapfst_Weight *__pyx_vtabptr_9pywrapfst_Weigh
 
 struct __pyx_vtabstruct_9pywrapfst__SymbolTable {
   __pyx_t_10basictypes_int64 (*available_key)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch);
-  std::string (*checksum)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch);
+  PyObject *(*checksum)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch);
   struct __pyx_obj_9pywrapfst_SymbolTable *(*copy)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch);
   __pyx_t_10basictypes_int64 (*get_nth_key)(struct __pyx_obj_9pywrapfst__SymbolTable *, Py_ssize_t, int __pyx_skip_dispatch);
-  std::string (*labeled_checksum)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch);
+  PyObject *(*labeled_checksum)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch);
   bool (*member)(struct __pyx_obj_9pywrapfst__SymbolTable *, PyObject *, int __pyx_skip_dispatch);
   std::string (*name)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch);
   size_t (*num_symbols)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch);
   void (*write)(struct __pyx_obj_9pywrapfst__SymbolTable *, PyObject *, int __pyx_skip_dispatch);
   void (*write_text)(struct __pyx_obj_9pywrapfst__SymbolTable *, PyObject *, int __pyx_skip_dispatch);
+  PyObject *(*write_to_string)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch);
 };
 static struct __pyx_vtabstruct_9pywrapfst__SymbolTable *__pyx_vtabptr_9pywrapfst__SymbolTable;
 
 
-/* "pywrapfst.pyx":839
+/* "pywrapfst.pyx":848
  * 
  * 
  * cdef class _EncodeMapperSymbolTable(_SymbolTable):             # <<<<<<<<<<<<<<
@@ -1851,7 +1899,7 @@ struct __pyx_vtabstruct_9pywrapfst__EncodeMapperSymbolTable {
 static struct __pyx_vtabstruct_9pywrapfst__EncodeMapperSymbolTable *__pyx_vtabptr_9pywrapfst__EncodeMapperSymbolTable;
 
 
-/* "pywrapfst.pyx":859
+/* "pywrapfst.pyx":868
  * 
  * 
  * cdef class _FstSymbolTable(_SymbolTable):             # <<<<<<<<<<<<<<
@@ -1865,7 +1913,7 @@ struct __pyx_vtabstruct_9pywrapfst__FstSymbolTable {
 static struct __pyx_vtabstruct_9pywrapfst__FstSymbolTable *__pyx_vtabptr_9pywrapfst__FstSymbolTable;
 
 
-/* "pywrapfst.pyx":878
+/* "pywrapfst.pyx":887
  * 
  * 
  * cdef class _MutableSymbolTable(_SymbolTable):             # <<<<<<<<<<<<<<
@@ -1882,7 +1930,7 @@ struct __pyx_vtabstruct_9pywrapfst__MutableSymbolTable {
 static struct __pyx_vtabstruct_9pywrapfst__MutableSymbolTable *__pyx_vtabptr_9pywrapfst__MutableSymbolTable;
 
 
-/* "pywrapfst.pyx":930
+/* "pywrapfst.pyx":939
  * 
  * 
  * cdef class _MutableFstSymbolTable(_MutableSymbolTable):             # <<<<<<<<<<<<<<
@@ -1896,7 +1944,7 @@ struct __pyx_vtabstruct_9pywrapfst__MutableFstSymbolTable {
 static struct __pyx_vtabstruct_9pywrapfst__MutableFstSymbolTable *__pyx_vtabptr_9pywrapfst__MutableFstSymbolTable;
 
 
-/* "pywrapfst.pyx":941
+/* "pywrapfst.pyx":950
  * 
  * 
  * cdef class SymbolTable(_MutableSymbolTable):             # <<<<<<<<<<<<<<
@@ -1910,7 +1958,7 @@ struct __pyx_vtabstruct_9pywrapfst_SymbolTable {
 static struct __pyx_vtabstruct_9pywrapfst_SymbolTable *__pyx_vtabptr_9pywrapfst_SymbolTable;
 
 
-/* "pywrapfst.pyx":1124
+/* "pywrapfst.pyx":1145
  * 
  * 
  * cdef class SymbolTableIterator(object):             # <<<<<<<<<<<<<<
@@ -1928,7 +1976,7 @@ struct __pyx_vtabstruct_9pywrapfst_SymbolTableIterator {
 static struct __pyx_vtabstruct_9pywrapfst_SymbolTableIterator *__pyx_vtabptr_9pywrapfst_SymbolTableIterator;
 
 
-/* "pywrapfst.pyx":1206
+/* "pywrapfst.pyx":1227
  * 
  * 
  * cdef class EncodeMapper(object):             # <<<<<<<<<<<<<<
@@ -1949,7 +1997,7 @@ struct __pyx_vtabstruct_9pywrapfst_EncodeMapper {
 static struct __pyx_vtabstruct_9pywrapfst_EncodeMapper *__pyx_vtabptr_9pywrapfst_EncodeMapper;
 
 
-/* "pywrapfst.pyx":1362
+/* "pywrapfst.pyx":1383
  * 
  * 
  * cdef class _Fst(object):             # <<<<<<<<<<<<<<
@@ -1958,6 +2006,7 @@ static struct __pyx_vtabstruct_9pywrapfst_EncodeMapper *__pyx_vtabptr_9pywrapfst
  */
 
 struct __pyx_vtabstruct_9pywrapfst__Fst {
+  std::string (*_local_render_svg)(std::string const &);
   std::string (*arc_type)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch);
   struct __pyx_obj_9pywrapfst_ArcIterator *(*arcs)(struct __pyx_obj_9pywrapfst__Fst *, __pyx_t_10basictypes_int64, int __pyx_skip_dispatch);
   struct __pyx_obj_9pywrapfst__Fst *(*copy)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch);
@@ -1976,12 +2025,12 @@ struct __pyx_vtabstruct_9pywrapfst__Fst {
   bool (*verify)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch);
   std::string (*weight_type)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch);
   void (*write)(struct __pyx_obj_9pywrapfst__Fst *, PyObject *, int __pyx_skip_dispatch);
-  std::string (*write_to_string)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch);
+  PyObject *(*write_to_string)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch);
 };
 static struct __pyx_vtabstruct_9pywrapfst__Fst *__pyx_vtabptr_9pywrapfst__Fst;
 
 
-/* "pywrapfst.pyx":1774
+/* "pywrapfst.pyx":1798
  * 
  * 
  * cdef class _MutableFst(_Fst):             # <<<<<<<<<<<<<<
@@ -2026,7 +2075,7 @@ struct __pyx_vtabstruct_9pywrapfst__MutableFst {
 static struct __pyx_vtabstruct_9pywrapfst__MutableFst *__pyx_vtabptr_9pywrapfst__MutableFst;
 
 
-/* "pywrapfst.pyx":2898
+/* "pywrapfst.pyx":2916
  * 
  * 
  * cdef class Arc(object):             # <<<<<<<<<<<<<<
@@ -2040,7 +2089,7 @@ struct __pyx_vtabstruct_9pywrapfst_Arc {
 static struct __pyx_vtabstruct_9pywrapfst_Arc *__pyx_vtabptr_9pywrapfst_Arc;
 
 
-/* "pywrapfst.pyx":2965
+/* "pywrapfst.pyx":2983
  * 
  * 
  * cdef class ArcIterator(object):             # <<<<<<<<<<<<<<
@@ -2061,7 +2110,7 @@ struct __pyx_vtabstruct_9pywrapfst_ArcIterator {
 static struct __pyx_vtabstruct_9pywrapfst_ArcIterator *__pyx_vtabptr_9pywrapfst_ArcIterator;
 
 
-/* "pywrapfst.pyx":3076
+/* "pywrapfst.pyx":3094
  * 
  * 
  * cdef class MutableArcIterator(object):             # <<<<<<<<<<<<<<
@@ -2083,7 +2132,7 @@ struct __pyx_vtabstruct_9pywrapfst_MutableArcIterator {
 static struct __pyx_vtabstruct_9pywrapfst_MutableArcIterator *__pyx_vtabptr_9pywrapfst_MutableArcIterator;
 
 
-/* "pywrapfst.pyx":3190
+/* "pywrapfst.pyx":3208
  * 
  * 
  * cdef class StateIterator(object):             # <<<<<<<<<<<<<<
@@ -2100,7 +2149,7 @@ struct __pyx_vtabstruct_9pywrapfst_StateIterator {
 static struct __pyx_vtabstruct_9pywrapfst_StateIterator *__pyx_vtabptr_9pywrapfst_StateIterator;
 
 
-/* "pywrapfst.pyx":4088
+/* "pywrapfst.pyx":4106
  * 
  * 
  * cdef class Compiler(object):             # <<<<<<<<<<<<<<
@@ -2115,7 +2164,7 @@ struct __pyx_vtabstruct_9pywrapfst_Compiler {
 static struct __pyx_vtabstruct_9pywrapfst_Compiler *__pyx_vtabptr_9pywrapfst_Compiler;
 
 
-/* "pywrapfst.pyx":4215
+/* "pywrapfst.pyx":4236
  * 
  * 
  * cdef class FarReader(object):             # <<<<<<<<<<<<<<
@@ -2137,7 +2186,7 @@ struct __pyx_vtabstruct_9pywrapfst_FarReader {
 static struct __pyx_vtabstruct_9pywrapfst_FarReader *__pyx_vtabptr_9pywrapfst_FarReader;
 
 
-/* "pywrapfst.pyx":4361
+/* "pywrapfst.pyx":4383
  * 
  * 
  * cdef class FarWriter(object):             # <<<<<<<<<<<<<<
@@ -2244,6 +2293,18 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
 #else
 #define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs)
 #endif
+#define __Pyx_BUILD_ASSERT_EXPR(cond)\
+    (sizeof(char [1 - 2*!(cond)]) - 1)
+#ifndef Py_MEMBER_SIZE
+#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
+#endif
+  static size_t __pyx_pyframe_localsplus_offset = 0;
+  #include "frameobject.h"
+  #define __Pxy_PyFrame_Initialize_Offsets()\
+    ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\
+     (void)(__pyx_pyframe_localsplus_offset = PyFrame_Type.tp_basicsize - Py_MEMBER_SIZE(PyFrameObject, f_localsplus)))
+  #define __Pyx_PyFrame_GetLocalsplus(frame)\
+    (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset))
 #endif
 
 /* PyObjectCall.proto */
@@ -2253,6 +2314,9 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg
 #define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw)
 #endif
 
+/* PyObjectCall2Args.proto */
+static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2);
+
 /* PyObjectCallMethO.proto */
 #if CYTHON_COMPILING_IN_CPYTHON
 static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg);
@@ -2262,7 +2326,25 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject
 static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg);
 
 /* GetModuleGlobalName.proto */
-static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name);
+#if CYTHON_USE_DICT_VERSIONS
+#define __Pyx_GetModuleGlobalName(var, name)  {\
+    static PY_UINT64_T __pyx_dict_version = 0;\
+    static PyObject *__pyx_dict_cached_value = NULL;\
+    (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\
+        (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\
+        __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\
+}
+#define __Pyx_GetModuleGlobalNameUncached(var, name)  {\
+    PY_UINT64_T __pyx_dict_version;\
+    PyObject *__pyx_dict_cached_value;\
+    (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\
+}
+static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value);
+#else
+#define __Pyx_GetModuleGlobalName(var, name)  (var) = __Pyx__GetModuleGlobalName(name)
+#define __Pyx_GetModuleGlobalNameUncached(var, name)  (var) = __Pyx__GetModuleGlobalName(name)
+static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name);
+#endif
 
 /* PyThreadStateGet.proto */
 #if CYTHON_FAST_THREAD_STATE
@@ -2339,6 +2421,11 @@ static void __Pyx_WriteUnraisable(const char *name, int clineno,
 /* KeywordStringCheck.proto */
 static int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed);
 
+/* GetTopmostException.proto */
+#if CYTHON_USE_EXC_INFO_STACK
+static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate);
+#endif
+
 /* SaveResetException.proto */
 #if CYTHON_FAST_THREAD_STATE
 #define __Pyx_ExceptionSave(type, value, tb)  __Pyx__ExceptionSave(__pyx_tstate, type, value, tb)
@@ -2371,6 +2458,44 @@ static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject
 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb);
 #endif
 
+/* GetItemInt.proto */
+#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\
+    (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\
+    __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\
+    (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\
+               __Pyx_GetItemInt_Generic(o, to_py_func(i))))
+#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\
+    (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\
+    __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\
+    (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL))
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck);
+#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\
+    (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\
+    __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\
+    (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL))
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck);
+static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j);
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
+                                                     int is_list, int wraparound, int boundscheck);
+
+/* PyErrExceptionMatches.proto */
+#if CYTHON_FAST_THREAD_STATE
+#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err)
+static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err);
+#else
+#define __Pyx_PyErr_ExceptionMatches(err)  PyErr_ExceptionMatches(err)
+#endif
+
+/* SwapException.proto */
+#if CYTHON_FAST_THREAD_STATE
+#define __Pyx_ExceptionSwap(type, value, tb)  __Pyx__ExceptionSwap(__pyx_tstate, type, value, tb)
+static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb);
+#else
+static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb);
+#endif
+
 /* RaiseTooManyValuesToUnpack.proto */
 static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);
 
@@ -2440,16 +2565,9 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
 #include "descrobject.h"
 static PyObject* __Pyx_Method_ClassMethod(PyObject *method);
 
-/* PyErrExceptionMatches.proto */
-#if CYTHON_FAST_THREAD_STATE
-#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err)
-static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err);
-#else
-#define __Pyx_PyErr_ExceptionMatches(err)  PyErr_ExceptionMatches(err)
-#endif
-
 /* GetNameInClass.proto */
-static PyObject *__Pyx_GetNameInClass(PyObject *nmspace, PyObject *name);
+#define __Pyx_GetNameInClass(var, nmspace, name)  (var) = __Pyx__GetNameInClass(nmspace, name)
+static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name);
 
 /* FetchCommonType.proto */
 static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type);
@@ -2489,6 +2607,7 @@ typedef struct {
     PyObject *func_annotations;
 } __pyx_CyFunctionObject;
 static PyTypeObject *__pyx_CyFunctionType = 0;
+#define __Pyx_CyFunction_Check(obj)  (__Pyx_TypeCheck(obj, __pyx_CyFunctionType))
 #define __Pyx_CyFunction_NewEx(ml, flags, qualname, self, module, globals, code)\
     __Pyx_CyFunction_New(__pyx_CyFunctionType, ml, flags, qualname, self, module, globals, code)
 static PyObject *__Pyx_CyFunction_New(PyTypeObject *, PyMethodDef *ml,
@@ -2551,13 +2670,16 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line,
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value);
 
 /* CIntToPy.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int64_t(int64_t value);
+
+/* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint64_t(uint64_t value);
 
 /* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint32_t(uint32_t value);
 
 /* CIntToPy.proto */
-static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int64_t(int64_t value);
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value);
 
 /* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int32_t(int32_t value);
@@ -2622,9 +2744,6 @@ static CYTHON_INLINE uint32_t __Pyx_PyInt_As_uint32_t(PyObject *);
 /* CIntFromPy.proto */
 static CYTHON_INLINE time_t __Pyx_PyInt_As_time_t(PyObject *);
 
-/* CIntToPy.proto */
-static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value);
-
 /* CIntFromPy.proto */
 static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *);
 
@@ -2645,15 +2764,16 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst_6Weight_copy(struc
 static std::string __pyx_f_9pywrapfst_6Weight_to_string(struct __pyx_obj_9pywrapfst_Weight *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static std::string __pyx_f_9pywrapfst_6Weight_type(struct __pyx_obj_9pywrapfst_Weight *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_12_SymbolTable_available_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
-static std::string __pyx_f_9pywrapfst_12_SymbolTable_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
+static PyObject *__pyx_f_9pywrapfst_12_SymbolTable_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_12_SymbolTable_copy(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_12_SymbolTable_get_nth_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, Py_ssize_t __pyx_v_pos, int __pyx_skip_dispatch); /* proto*/
-static std::string __pyx_f_9pywrapfst_12_SymbolTable_labeled_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
+static PyObject *__pyx_f_9pywrapfst_12_SymbolTable_labeled_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key, int __pyx_skip_dispatch); /* proto*/
 static std::string __pyx_f_9pywrapfst_12_SymbolTable_name(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static size_t __pyx_f_9pywrapfst_12_SymbolTable_num_symbols(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static void __pyx_f_9pywrapfst_12_SymbolTable_write(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename, int __pyx_skip_dispatch); /* proto*/
 static void __pyx_f_9pywrapfst_12_SymbolTable_write_text(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename, int __pyx_skip_dispatch); /* proto*/
+static PyObject *__pyx_f_9pywrapfst_12_SymbolTable_write_to_string(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_19_MutableSymbolTable_add_symbol(struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self, PyObject *__pyx_v_symbol, int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_19_MutableSymbolTable_add_symbol *__pyx_optional_args); /* proto*/
 static void __pyx_f_9pywrapfst_19_MutableSymbolTable_add_table(struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms, int __pyx_skip_dispatch); /* proto*/
 static void __pyx_f_9pywrapfst_19_MutableSymbolTable_set_name(struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self, PyObject *__pyx_v_new_name, int __pyx_skip_dispatch); /* proto*/
@@ -2670,6 +2790,7 @@ static __pyx_t_10basictypes_uint64 __pyx_f_9pywrapfst_12EncodeMapper_properties(
 static void __pyx_f_9pywrapfst_12EncodeMapper_set_input_symbols(struct __pyx_obj_9pywrapfst_EncodeMapper *__pyx_v_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms, int __pyx_skip_dispatch); /* proto*/
 static void __pyx_f_9pywrapfst_12EncodeMapper_set_output_symbols(struct __pyx_obj_9pywrapfst_EncodeMapper *__pyx_v_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms, int __pyx_skip_dispatch); /* proto*/
 static std::string __pyx_f_9pywrapfst_12EncodeMapper_weight_type(struct __pyx_obj_9pywrapfst_EncodeMapper *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
+static std::string __pyx_f_9pywrapfst_4_Fst__local_render_svg(std::string const &__pyx_v_dot); /* proto*/
 static std::string __pyx_f_9pywrapfst_4_Fst_arc_type(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static struct __pyx_obj_9pywrapfst_ArcIterator *__pyx_f_9pywrapfst_4_Fst_arcs(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, __pyx_t_10basictypes_int64 __pyx_v_state, int __pyx_skip_dispatch); /* proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_4_Fst_copy(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
@@ -2688,7 +2809,7 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
 static bool __pyx_f_9pywrapfst_4_Fst_verify(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static std::string __pyx_f_9pywrapfst_4_Fst_weight_type(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static void __pyx_f_9pywrapfst_4_Fst_write(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, PyObject *__pyx_v_filename, int __pyx_skip_dispatch); /* proto*/
-static std::string __pyx_f_9pywrapfst_4_Fst_write_to_string(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
+static PyObject *__pyx_f_9pywrapfst_4_Fst_write_to_string(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
 static void __pyx_f_9pywrapfst_11_MutableFst__check_mutating_imethod(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self); /* proto*/
 static void __pyx_f_9pywrapfst_11_MutableFst__add_arc(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self, __pyx_t_10basictypes_int64 __pyx_v_state, struct __pyx_obj_9pywrapfst_Arc *__pyx_v_arc); /* proto*/
 static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_11_MutableFst_add_state(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
@@ -2829,12 +2950,13 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
 static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst__init_FstSymbolTable(fst::SymbolTable *, std::shared_ptr<fst::script::FstClass> ); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_f_9pywrapfst__init_MutableFstSymbolTable(fst::SymbolTable *, std::shared_ptr<fst::script::MutableFstClass> ); /*proto*/
 static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst__init_SymbolTable(fst::SymbolTable *); /*proto*/
+static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst__read_SymbolTable_from_string(PyObject *, int __pyx_skip_dispatch); /*proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_Fst(__pyx_t_9pywrapfst_FstClass_ptr); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__init_MutableFst(__pyx_t_9pywrapfst_MutableFstClass_ptr); /*proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_XFst(__pyx_t_9pywrapfst_FstClass_ptr); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(struct __pyx_opt_args_9pywrapfst__create_Fst *__pyx_optional_args); /*proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *, int __pyx_skip_dispatch); /*proto*/
-static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read_from_string(PyObject *, int __pyx_skip_dispatch); /*proto*/
+static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read_Fst_from_string(PyObject *, int __pyx_skip_dispatch); /*proto*/
 static struct __pyx_obj_9pywrapfst_Arc *__pyx_f_9pywrapfst__init_Arc(fst::script::ArcClass const &); /*proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_obj_9pywrapfst__Fst *, struct __pyx_opt_args_9pywrapfst__map *__pyx_optional_args); /*proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_arcmap(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_arcmap *__pyx_optional_args); /*proto*/
@@ -2867,7 +2989,6 @@ static CYTHON_INLINE PyObject *__pyx_convert_PyStr_string_to_py_std__in_string(s
 static CYTHON_INLINE PyObject *__pyx_convert_PyBytes_string_to_py_std__in_string(std::string const &); /*proto*/
 static CYTHON_INLINE PyObject *__pyx_convert_PyByteArray_string_to_py_std__in_string(std::string const &); /*proto*/
 static std::vector<__pyx_t_10basictypes_int64>  __pyx_convert_vector_from_py___pyx_t_10basictypes_int64(PyObject *); /*proto*/
-static std::vector<std::string>  __pyx_convert_vector_from_py_std_3a__3a_string(PyObject *); /*proto*/
 #define __Pyx_MODULE_NAME "pywrapfst"
 extern int __pyx_module_is_main_pywrapfst;
 int __pyx_module_is_main_pywrapfst = 0;
@@ -2887,9 +3008,10 @@ static const char __pyx_k_g[] = "g";
 static const char __pyx_k_n[] = "n";
 static const char __pyx_k_w[] = "w";
 static const char __pyx_k_id[] = "id";
-static const char __pyx_k_Fst[] = "Fst";
+static const char __pyx_k_Arc[] = "Arc";
+static const char __pyx_k_Fst[] = "_Fst";
 static const char __pyx_k_One[] = "One";
-static const char __pyx_k__24[] = "";
+static const char __pyx_k__10[] = "";
 static const char __pyx_k_add[] = "add";
 static const char __pyx_k_arc[] = "arc";
 static const char __pyx_k_cls[] = "cls";
@@ -2924,6 +3046,7 @@ static const char __pyx_k_text[] = "text";
 static const char __pyx_k_type[] = "type";
 static const char __pyx_k_utf8[] = "utf8";
 static const char __pyx_k_ERROR[] = "ERROR";
+static const char __pyx_k_Fst_2[] = "Fst";
 static const char __pyx_k_Popen[] = "Popen";
 static const char __pyx_k_class[] = "__class__";
 static const char __pyx_k_delta[] = "delta";
@@ -2949,9 +3072,8 @@ static const char __pyx_k_write[] = "write";
 static const char __pyx_k_CYCLIC[] = "CYCLIC";
 static const char __pyx_k_Number[] = "Number";
 static const char __pyx_k_STRING[] = "STRING";
-static const char __pyx_k_atexit[] = "atexit";
+static const char __pyx_k_Weight[] = "Weight";
 static const char __pyx_k_create[] = "create";
-static const char __pyx_k_decode[] = "decode";
 static const char __pyx_k_divide[] = "divide";
 static const char __pyx_k_encode[] = "encode";
 static const char __pyx_k_format[] = "format";
@@ -2970,7 +3092,6 @@ static const char __pyx_k_reduce[] = "__reduce__";
 static const char __pyx_k_result[] = "result";
 static const char __pyx_k_select[] = "select";
 static const char __pyx_k_states[] = "states";
-static const char __pyx_k_stderr[] = "stderr";
 static const char __pyx_k_stdout[] = "stdout";
 static const char __pyx_k_symbol[] = "symbol";
 static const char __pyx_k_test_2[] = "__test__";
@@ -2996,7 +3117,7 @@ static const char __pyx_k_reverse[] = "reverse";
 static const char __pyx_k_uniform[] = "uniform";
 static const char __pyx_k_warning[] = "warning";
 static const char __pyx_k_ACCEPTOR[] = "ACCEPTOR";
-static const char __pyx_k_DOT_TSVG[] = "_DOT_TSVG";
+static const char __pyx_k_Compiler[] = "Compiler";
 static const char __pyx_k_EPSILONS[] = "EPSILONS";
 static const char __pyx_k_EXPANDED[] = "EXPANDED";
 static const char __pyx_k_FstError[] = "FstError";
@@ -3024,8 +3145,6 @@ static const char __pyx_k_portrait[] = "portrait";
 static const char __pyx_k_position[] = "position";
 static const char __pyx_k_qualname[] = "__qualname__";
 static const char __pyx_k_read_fst[] = "read_fst";
-static const char __pyx_k_register[] = "register";
-static const char __pyx_k_repr_svg[] = "_repr_svg";
 static const char __pyx_k_set_name[] = "set_name";
 static const char __pyx_k_setstate[] = "__setstate__";
 static const char __pyx_k_ssymbols[] = "ssymbols";
@@ -3035,12 +3154,13 @@ static const char __pyx_k_tropical[] = "tropical";
 static const char __pyx_k_vertical[] = "vertical";
 static const char __pyx_k_weighted[] = "weighted";
 static const char __pyx_k_ARC_FLAGS[] = "ARC_FLAGS";
+static const char __pyx_k_FarReader[] = "FarReader";
+static const char __pyx_k_FarWriter[] = "FarWriter";
 static const char __pyx_k_Fst___new[] = "Fst.__new__";
 static const char __pyx_k_NO_SYMBOL[] = "NO_SYMBOL";
 static const char __pyx_k_TypeError[] = "TypeError";
 static const char __pyx_k_add_state[] = "add_state";
 static const char __pyx_k_add_table[] = "add_table";
-static const char __pyx_k_kNoSymbol[] = "kNoSymbol";
 static const char __pyx_k_metaclass[] = "__metaclass__";
 static const char __pyx_k_nextstate[] = "nextstate";
 static const char __pyx_k_nshortest[] = "nshortest";
@@ -3057,6 +3177,7 @@ static const char __pyx_k_FstIOError[] = "FstIOError";
 static const char __pyx_k_FstOpError[] = "FstOpError";
 static const char __pyx_k_I_EPSILONS[] = "I_EPSILONS";
 static const char __pyx_k_IndexError[] = "IndexError";
+static const char __pyx_k_MutableFst[] = "_MutableFst";
 static const char __pyx_k_NOT_STRING[] = "NOT_STRING";
 static const char __pyx_k_O_EPSILONS[] = "O_EPSILONS";
 static const char __pyx_k_TOP_SORTED[] = "TOP_SORTED";
@@ -3070,14 +3191,16 @@ static const char __pyx_k_potentials[] = "potentials";
 static const char __pyx_k_properties[] = "properties";
 static const char __pyx_k_pyx_vtable[] = "__pyx_vtable__";
 static const char __pyx_k_queue_type[] = "queue_type";
-static const char __pyx_k_returncode[] = "returncode";
 static const char __pyx_k_subprocess[] = "subprocess";
 static const char __pyx_k_write_text[] = "write_text";
+static const char __pyx_k_ArcIterator[] = "ArcIterator";
 static const char __pyx_k_Arc_at_0x_x[] = "<Arc at 0x{:x}>";
 static const char __pyx_k_FstArgError[] = "FstArgError";
 static const char __pyx_k_Fst_at_0x_x[] = "<{} Fst at 0x{:x}>";
 static const char __pyx_k_NO_EPSILONS[] = "NO_EPSILONS";
 static const char __pyx_k_NO_STATE_ID[] = "NO_STATE_ID";
+static const char __pyx_k_Read_failed[] = "Read failed";
+static const char __pyx_k_SymbolTable[] = "_SymbolTable";
 static const char __pyx_k_communicate[] = "communicate";
 static const char __pyx_k_get_nth_key[] = "get_nth_key";
 static const char __pyx_k_input_table[] = "input_table";
@@ -3090,6 +3213,7 @@ static const char __pyx_k_weight_type[] = "weight_type";
 static const char __pyx_k_ARC_NO_CACHE[] = "ARC_NO_CACHE";
 static const char __pyx_k_COACCESSIBLE[] = "COACCESSIBLE";
 static const char __pyx_k_ENCODE_FLAGS[] = "ENCODE_FLAGS";
+static const char __pyx_k_EncodeMapper[] = "EncodeMapper";
 static const char __pyx_k_NOT_ACCEPTOR[] = "NOT_ACCEPTOR";
 static const char __pyx_k_RuntimeError[] = "RuntimeError";
 static const char __pyx_k_allow_nondet[] = "allow_nondet";
@@ -3109,7 +3233,9 @@ static const char __pyx_k_NO_I_EPSILONS[] = "NO_I_EPSILONS";
 static const char __pyx_k_NO_O_EPSILONS[] = "NO_O_EPSILONS";
 static const char __pyx_k_Open_failed_r[] = "Open failed: {!r}";
 static const char __pyx_k_Read_failed_r[] = "Read failed: {!r}";
+static const char __pyx_k_StateIterator[] = "StateIterator";
 static const char __pyx_k_StopIteration[] = "StopIteration";
+static const char __pyx_k_SymbolTable_2[] = "SymbolTable";
 static const char __pyx_k_available_key[] = "available_key";
 static const char __pyx_k_encode_labels[] = "encode_labels";
 static const char __pyx_k_input_symbols[] = "input_symbols";
@@ -3119,6 +3245,7 @@ static const char __pyx_k_pywrapfst_pyx[] = "pywrapfst.pyx";
 static const char __pyx_k_reduce_cython[] = "__reduce_cython__";
 static const char __pyx_k_ENCODE_WEIGHTS[] = "ENCODE_WEIGHTS";
 static const char __pyx_k_FST_PROPERTIES[] = "FST_PROPERTIES";
+static const char __pyx_k_FstSymbolTable[] = "_FstSymbolTable";
 static const char __pyx_k_INITIAL_CYCLIC[] = "INITIAL_CYCLIC";
 static const char __pyx_k_I_LABEL_SORTED[] = "I_LABEL_SORTED";
 static const char __pyx_k_Invalid_weight[] = "Invalid weight";
@@ -3150,7 +3277,7 @@ static const char __pyx_k_Key_out_of_order[] = "Key out of order";
 static const char __pyx_k_NOT_COACCESSIBLE[] = "NOT_COACCESSIBLE";
 static const char __pyx_k_Operation_failed[] = "Operation failed";
 static const char __pyx_k_labeled_checksum[] = "labeled_checksum";
-static const char __pyx_k_read_from_string[] = "_read_from_string";
+static const char __pyx_k_read_from_string[] = "read_from_string";
 static const char __pyx_k_shortestdistance[] = "shortestdistance";
 static const char __pyx_k_ARC_I_LABEL_VALUE[] = "ARC_I_LABEL_VALUE";
 static const char __pyx_k_ARC_O_LABEL_VALUE[] = "ARC_O_LABEL_VALUE";
@@ -3162,11 +3289,11 @@ static const char __pyx_k_UNWEIGHTED_CYCLES[] = "UNWEIGHTED_CYCLES";
 static const char __pyx_k_call_arc_labeling[] = "call_arc_labeling";
 static const char __pyx_k_set_input_symbols[] = "set_input_symbols";
 static const char __pyx_k_ADD_ARC_PROPERTIES[] = "ADD_ARC_PROPERTIES";
-static const char __pyx_k_CalledProcessError[] = "CalledProcessError";
 static const char __pyx_k_Compilation_failed[] = "Compilation failed";
+static const char __pyx_k_MutableArcIterator[] = "MutableArcIterator";
+static const char __pyx_k_MutableSymbolTable[] = "_MutableSymbolTable";
 static const char __pyx_k_NOT_I_LABEL_SORTED[] = "NOT_I_LABEL_SORTED";
 static const char __pyx_k_NOT_O_LABEL_SORTED[] = "NOT_O_LABEL_SORTED";
-static const char __pyx_k_Read_failed_string[] = "Read failed: <string>";
 static const char __pyx_k_SET_ARC_PROPERTIES[] = "SET_ARC_PROPERTIES";
 static const char __pyx_k_TRINARY_PROPERTIES[] = "TRINARY_PROPERTIES";
 static const char __pyx_k_Unknown_arc_type_r[] = "Unknown arc type: {!r}";
@@ -3174,16 +3301,15 @@ static const char __pyx_k_Unknown_map_type_r[] = "Unknown map type: {!r}";
 static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback";
 static const char __pyx_k_epsilon_on_replace[] = "epsilon_on_replace";
 static const char __pyx_k_num_input_epsilons[] = "num_input_epsilons";
-static const char __pyx_k_read_from_string_2[] = "read_from_string";
 static const char __pyx_k_set_output_symbols[] = "set_output_symbols";
 static const char __pyx_k_ARC_SORT_PROPERTIES[] = "ARC_SORT_PROPERTIES";
 static const char __pyx_k_ArcIterator_at_0x_x[] = "<ArcIterator at 0x{:x}>";
 static const char __pyx_k_NON_I_DETERMINISTIC[] = "NON_I_DETERMINISTIC";
 static const char __pyx_k_NON_O_DETERMINISTIC[] = "NON_O_DETERMINISTIC";
+static const char __pyx_k_SymbolTableIterator[] = "SymbolTableIterator";
 static const char __pyx_k_Unknown_sort_type_r[] = "Unknown sort type {!r}";
 static const char __pyx_k_attach_new_isymbols[] = "attach_new_isymbols";
 static const char __pyx_k_attach_new_osymbols[] = "attach_new_osymbols";
-static const char __pyx_k_fst_error_fatal_old[] = "_fst_error_fatal_old";
 static const char __pyx_k_num_output_epsilons[] = "num_output_epsilons";
 static const char __pyx_k_remove_common_affix[] = "remove_common_affix";
 static const char __pyx_k_remove_total_weight[] = "remove_total_weight";
@@ -3191,6 +3317,7 @@ static const char __pyx_k_return_arc_labeling[] = "return_arc_labeling";
 static const char __pyx_k_subsequential_label[] = "subsequential_label";
 static const char __pyx_k_ADD_STATE_PROPERTIES[] = "ADD_STATE_PROPERTIES";
 static const char __pyx_k_ARC_NEXT_STATE_VALUE[] = "ARC_NEXT_STATE_VALUE";
+static const char __pyx_k_Dot_rendering_failed[] = "Dot rendering failed: ";
 static const char __pyx_k_EXTRINSIC_PROPERTIES[] = "EXTRINSIC_PROPERTIES";
 static const char __pyx_k_EncodeMapper_at_0x_x[] = "<EncodeMapper at 0x{:x}>";
 static const char __pyx_k_Fst_read_from_string[] = "Fst.read_from_string";
@@ -3199,19 +3326,21 @@ static const char __pyx_k_SET_FINAL_PROPERTIES[] = "SET_FINAL_PROPERTIES";
 static const char __pyx_k_SET_START_PROPERTIES[] = "SET_START_PROPERTIES";
 static const char __pyx_k_Unknown_queue_type_r[] = "Unknown queue type: {!r}";
 static const char __pyx_k_keep_state_numbering[] = "keep_state_numbering";
+static const char __pyx_k_read_Fst_from_string[] = "_read_Fst_from_string";
 static const char __pyx_k_require_superinitial[] = "require_superinitial";
 static const char __pyx_k_DELETE_ARC_PROPERTIES[] = "DELETE_ARC_PROPERTIES";
+static const char __pyx_k_MutableFstSymbolTable[] = "_MutableFstSymbolTable";
 static const char __pyx_k_STATE_SORT_PROPERTIES[] = "STATE_SORT_PROPERTIES";
 static const char __pyx_k_StateIterator_at_0x_x[] = "<StateIterator at 0x{:x}>";
 static const char __pyx_k_SymbolTable_r_at_0x_x[] = "<SymbolTable {!r} at 0x{:x}>";
 static const char __pyx_k_Weight_type_not_found[] = "Weight type not found";
 static const char __pyx_k_allow_negative_labels[] = "allow_negative_labels";
-static const char __pyx_k_reset_fst_error_fatal[] = "_reset_fst_error_fatal";
 static const char __pyx_k_Conversion_to_r_failed[] = "Conversion to {!r} failed";
 static const char __pyx_k_NEG_TRINARY_PROPERTIES[] = "NEG_TRINARY_PROPERTIES";
 static const char __pyx_k_POS_TRINARY_PROPERTIES[] = "POS_TRINARY_PROPERTIES";
 static const char __pyx_k_Write_to_string_failed[] = "Write to string failed";
 static const char __pyx_k_DELETE_STATE_PROPERTIES[] = "DELETE_STATE_PROPERTIES";
+static const char __pyx_k_EncodeMapperSymbolTable[] = "_EncodeMapperSymbolTable";
 static const char __pyx_k_RM_SUPERFINAL_PROPERTIES[] = "RM_SUPERFINAL_PROPERTIES";
 static const char __pyx_k_State_index_out_of_range[] = "State index out of range";
 static const char __pyx_k_ADD_SUPERFINAL_PROPERTIES[] = "ADD_SUPERFINAL_PROPERTIES";
@@ -3225,6 +3354,7 @@ static const char __pyx_k_WEIGHT_INVARIANT_PROPERTIES[] = "WEIGHT_INVARIANT_PROP
 static const char __pyx_k_I_LABEL_INVARIANT_PROPERTIES[] = "I_LABEL_INVARIANT_PROPERTIES";
 static const char __pyx_k_O_LABEL_INVARIANT_PROPERTIES[] = "O_LABEL_INVARIANT_PROPERTIES";
 static const char __pyx_k_Unknown_replace_label_type_r[] = "Unknown replace label type: {!r}";
+static const char __pyx_k_read_SymbolTable_from_string[] = "_read_SymbolTable_from_string";
 static const char __pyx_k_No_new_SymbolTables_specified[] = "No new SymbolTables specified";
 static const char __pyx_k_No_relabeling_pairs_specified[] = "No relabeling pairs specified.";
 static const char __pyx_k_Unknown_compose_filter_type_r[] = "Unknown compose filter type: {!r}";
@@ -3236,8 +3366,6 @@ static const char __pyx_k_Fst_arc_type_standard_Construct[] = "\n   Fst(arc_type
 static const char __pyx_k_const_Fst_SymbolTable_r_at_0x_x[] = "<const Fst SymbolTable {!r} at 0x{:x}>";
 static const char __pyx_k_self__aiter_self__fst_cannot_be[] = "self._aiter,self._fst cannot be converted to a Python object for pickling";
 static const char __pyx_k_self__fst_self__siter_cannot_be[] = "self._fst,self._siter cannot be converted to a Python object for pickling";
-static const char __pyx_k_self__fst_self__table_cannot_be[] = "self._fst,self._table cannot be converted to a Python object for pickling";
-static const char __pyx_k_self__table_cannot_be_converted[] = "self._table cannot be converted to a Python object for pickling";
 static const char __pyx_k_Incompatible_or_invalid_arc_type[] = "Incompatible or invalid arc type";
 static const char __pyx_k_Incompatible_or_invalid_weight_t[] = "Incompatible or invalid weight type";
 static const char __pyx_k_Python_interface_to_the_FST_scri[] = "Python interface to the FST scripting API.\n\nOperations which construct new FSTs are implemented as traditional functions, as\nare two-argument boolean functions like `equal` and `equivalent`. Destructive\noperations---those that mutate an FST, in place---are instance methods, as is\n`write`. Operator overloading is not used. The following example, based on\nMohri et al. 2002, shows the construction of an ASR system given a pronunciation\nlexicon L, grammar G, a transducer from context-dependent phones to\ncontext-independent phones C, and an HMM set H:\n\n  L = fst.Fst.read(\"L.fst\")\n  G = fst.Fst.read(\"G.fst\")\n  C = fst.Fst.read(\"C.fst\")\n  H = fst.Fst.read(\"H.fst\")\n  LG = fst.determinize(fst.compose(L, G))\n  CLG = fst.determinize(fst.compose(C, LG))\n  HCLG = fst.determinize(fst.compose(H, CLG))\n  HCLG.minimize()                                      # NB: works in-place.\n\nPython variables here use snake_case and constants are in all caps, minus the\nnormal `k` prefix.\n";
@@ -3246,11 +3374,8 @@ static const char __pyx_k_no_default___reduce___due_to_non[] = "no default __red
 static const char __pyx_k_self__aiter_self__mfst_cannot_be[] = "self._aiter,self._mfst cannot be converted to a Python object for pickling";
 static const char __pyx_k_self__arc_cannot_be_converted_to[] = "self._arc cannot be converted to a Python object for pickling";
 static const char __pyx_k_self__encoder_cannot_be_converte[] = "self._encoder cannot be converted to a Python object for pickling";
-static const char __pyx_k_self__encoder_self__table_cannot[] = "self._encoder,self._table cannot be converted to a Python object for pickling";
-static const char __pyx_k_self__mfst_self__table_cannot_be[] = "self._mfst,self._table cannot be converted to a Python object for pickling";
 static const char __pyx_k_self__reader_cannot_be_converted[] = "self._reader cannot be converted to a Python object for pickling";
 static const char __pyx_k_self__siter_self__table_cannot_b[] = "self._siter,self._table cannot be converted to a Python object for pickling";
-static const char __pyx_k_self__smart_table_self__table_ca[] = "self._smart_table,self._table cannot be converted to a Python object for pickling";
 static const char __pyx_k_self__weight_cannot_be_converted[] = "self._weight cannot be converted to a Python object for pickling";
 static const char __pyx_k_self__writer_cannot_be_converted[] = "self._writer cannot be converted to a Python object for pickling";
 static PyObject *__pyx_n_s_ACCEPTOR;
@@ -3267,21 +3392,23 @@ static PyObject *__pyx_n_s_ARC_O_LABEL_VALUE;
 static PyObject *__pyx_n_s_ARC_SORT_PROPERTIES;
 static PyObject *__pyx_n_s_ARC_VALUE_FLAGS;
 static PyObject *__pyx_n_s_ARC_WEIGHT_VALUE;
-static PyObject *__pyx_kp_s_ArcIterator_at_0x_x;
-static PyObject *__pyx_kp_s_Arc_at_0x_x;
+static PyObject *__pyx_n_s_Arc;
+static PyObject *__pyx_n_s_ArcIterator;
+static PyObject *__pyx_kp_u_ArcIterator_at_0x_x;
+static PyObject *__pyx_kp_u_Arc_at_0x_x;
 static PyObject *__pyx_n_s_BINARY_PROPERTIES;
 static PyObject *__pyx_n_s_COACCESSIBLE;
 static PyObject *__pyx_n_s_COPY_PROPERTIES;
 static PyObject *__pyx_n_s_CYCLIC;
-static PyObject *__pyx_n_s_CalledProcessError;
-static PyObject *__pyx_kp_s_Cannot_construct;
-static PyObject *__pyx_kp_s_Cannot_encode_as_string_r;
-static PyObject *__pyx_kp_s_Cannot_topsort_cyclic_FST;
-static PyObject *__pyx_kp_s_Compilation_failed;
-static PyObject *__pyx_kp_s_Conversion_to_r_failed;
+static PyObject *__pyx_kp_u_Cannot_construct;
+static PyObject *__pyx_kp_u_Cannot_encode_as_string_r;
+static PyObject *__pyx_kp_u_Cannot_topsort_cyclic_FST;
+static PyObject *__pyx_kp_u_Compilation_failed;
+static PyObject *__pyx_n_s_Compiler;
+static PyObject *__pyx_kp_u_Conversion_to_r_failed;
 static PyObject *__pyx_n_s_DELETE_ARC_PROPERTIES;
 static PyObject *__pyx_n_s_DELETE_STATE_PROPERTIES;
-static PyObject *__pyx_n_s_DOT_TSVG;
+static PyObject *__pyx_kp_u_Dot_rendering_failed;
 static PyObject *__pyx_n_s_ENCODE_FLAGS;
 static PyObject *__pyx_n_s_ENCODE_LABELS;
 static PyObject *__pyx_n_s_ENCODE_WEIGHTS;
@@ -3289,10 +3416,14 @@ static PyObject *__pyx_n_s_EPSILONS;
 static PyObject *__pyx_n_s_ERROR;
 static PyObject *__pyx_n_s_EXPANDED;
 static PyObject *__pyx_n_s_EXTRINSIC_PROPERTIES;
-static PyObject *__pyx_kp_s_EncodeMapper_at_0x_x;
+static PyObject *__pyx_n_s_EncodeMapper;
+static PyObject *__pyx_n_s_EncodeMapperSymbolTable;
+static PyObject *__pyx_kp_u_EncodeMapper_at_0x_x;
 static PyObject *__pyx_n_s_FST_PROPERTIES;
-static PyObject *__pyx_kp_s_FarReader_at_0x_x;
-static PyObject *__pyx_kp_s_FarWriter_at_0x_x;
+static PyObject *__pyx_n_s_FarReader;
+static PyObject *__pyx_kp_u_FarReader_at_0x_x;
+static PyObject *__pyx_n_s_FarWriter;
+static PyObject *__pyx_kp_u_FarWriter_at_0x_x;
 static PyObject *__pyx_n_s_Fst;
 static PyObject *__pyx_n_s_FstArgError;
 static PyObject *__pyx_n_s_FstBadWeightError;
@@ -3301,10 +3432,12 @@ static PyObject *__pyx_n_s_FstError;
 static PyObject *__pyx_n_s_FstIOError;
 static PyObject *__pyx_n_s_FstIndexError;
 static PyObject *__pyx_n_s_FstOpError;
-static PyObject *__pyx_kp_s_Fst_SymbolTable_r_at_0x_x;
+static PyObject *__pyx_n_s_FstSymbolTable;
+static PyObject *__pyx_n_s_Fst_2;
+static PyObject *__pyx_kp_u_Fst_SymbolTable_r_at_0x_x;
 static PyObject *__pyx_n_s_Fst___new;
 static PyObject *__pyx_kp_s_Fst_arc_type_standard_Construct;
-static PyObject *__pyx_kp_s_Fst_at_0x_x;
+static PyObject *__pyx_kp_u_Fst_at_0x_x;
 static PyObject *__pyx_n_s_Fst_read;
 static PyObject *__pyx_n_s_Fst_read_from_string;
 static PyObject *__pyx_n_s_INITIAL_ACYCLIC;
@@ -3315,15 +3448,19 @@ static PyObject *__pyx_n_s_I_DETERMINISTIC;
 static PyObject *__pyx_n_s_I_EPSILONS;
 static PyObject *__pyx_n_s_I_LABEL_INVARIANT_PROPERTIES;
 static PyObject *__pyx_n_s_I_LABEL_SORTED;
-static PyObject *__pyx_kp_s_Incompatible_or_invalid_arc_type;
-static PyObject *__pyx_kp_s_Incompatible_or_invalid_weight;
-static PyObject *__pyx_kp_s_Incompatible_or_invalid_weight_t;
+static PyObject *__pyx_kp_u_Incompatible_or_invalid_arc_type;
+static PyObject *__pyx_kp_u_Incompatible_or_invalid_weight;
+static PyObject *__pyx_kp_u_Incompatible_or_invalid_weight_t;
 static PyObject *__pyx_n_s_IndexError;
-static PyObject *__pyx_kp_s_Invalid_weight;
+static PyObject *__pyx_kp_u_Invalid_weight;
 static PyObject *__pyx_n_s_KeyError;
-static PyObject *__pyx_kp_s_Key_out_of_order;
+static PyObject *__pyx_kp_u_Key_out_of_order;
 static PyObject *__pyx_n_s_MUTABLE;
-static PyObject *__pyx_kp_s_MutableArcIterator_at_0x_x;
+static PyObject *__pyx_n_s_MutableArcIterator;
+static PyObject *__pyx_kp_u_MutableArcIterator_at_0x_x;
+static PyObject *__pyx_n_s_MutableFst;
+static PyObject *__pyx_n_s_MutableFstSymbolTable;
+static PyObject *__pyx_n_s_MutableSymbolTable;
 static PyObject *__pyx_n_s_NEG_TRINARY_PROPERTIES;
 static PyObject *__pyx_n_s_NON_I_DETERMINISTIC;
 static PyObject *__pyx_n_s_NON_O_DETERMINISTIC;
@@ -3342,57 +3479,62 @@ static PyObject *__pyx_n_s_NO_STATE_ID;
 static PyObject *__pyx_n_s_NO_SYMBOL;
 static PyObject *__pyx_n_s_NULL_PROPERTIES;
 static PyObject *__pyx_n_s_NoWeight;
-static PyObject *__pyx_kp_s_No_new_SymbolTables_specified;
-static PyObject *__pyx_kp_s_No_relabeling_pairs_specified;
+static PyObject *__pyx_kp_u_No_new_SymbolTables_specified;
+static PyObject *__pyx_kp_u_No_relabeling_pairs_specified;
 static PyObject *__pyx_n_s_Number;
 static PyObject *__pyx_n_s_O_DETERMINISTIC;
 static PyObject *__pyx_n_s_O_EPSILONS;
 static PyObject *__pyx_n_s_O_LABEL_INVARIANT_PROPERTIES;
 static PyObject *__pyx_n_s_O_LABEL_SORTED;
 static PyObject *__pyx_n_s_One;
-static PyObject *__pyx_kp_s_Open_failed_r;
-static PyObject *__pyx_kp_s_Operation_failed;
+static PyObject *__pyx_kp_u_Open_failed_r;
+static PyObject *__pyx_kp_u_Operation_failed;
 static PyObject *__pyx_n_s_PIPE;
 static PyObject *__pyx_n_s_POS_TRINARY_PROPERTIES;
 static PyObject *__pyx_n_s_Popen;
 static PyObject *__pyx_n_s_RM_SUPERFINAL_PROPERTIES;
-static PyObject *__pyx_kp_s_Read_failed_r;
-static PyObject *__pyx_kp_s_Read_failed_string;
+static PyObject *__pyx_kp_u_Read_failed;
+static PyObject *__pyx_kp_u_Read_failed_r;
 static PyObject *__pyx_n_s_RuntimeError;
 static PyObject *__pyx_n_s_SET_ARC_PROPERTIES;
 static PyObject *__pyx_n_s_SET_FINAL_PROPERTIES;
 static PyObject *__pyx_n_s_SET_START_PROPERTIES;
 static PyObject *__pyx_n_s_STATE_SORT_PROPERTIES;
 static PyObject *__pyx_n_s_STRING;
-static PyObject *__pyx_kp_s_StateIterator_at_0x_x;
-static PyObject *__pyx_kp_s_State_index_out_of_range;
+static PyObject *__pyx_n_s_StateIterator;
+static PyObject *__pyx_kp_u_StateIterator_at_0x_x;
+static PyObject *__pyx_kp_u_State_index_out_of_range;
 static PyObject *__pyx_n_s_StopIteration;
-static PyObject *__pyx_kp_s_SymbolTableIterator_at_0x_x;
-static PyObject *__pyx_kp_s_SymbolTable_r_at_0x_x;
+static PyObject *__pyx_n_s_SymbolTable;
+static PyObject *__pyx_n_s_SymbolTableIterator;
+static PyObject *__pyx_kp_u_SymbolTableIterator_at_0x_x;
+static PyObject *__pyx_n_s_SymbolTable_2;
+static PyObject *__pyx_kp_u_SymbolTable_r_at_0x_x;
 static PyObject *__pyx_n_s_TOP_SORTED;
 static PyObject *__pyx_n_s_TRINARY_PROPERTIES;
-static PyObject *__pyx_kp_s_Tsvg;
+static PyObject *__pyx_kp_u_Tsvg;
 static PyObject *__pyx_n_s_TypeError;
 static PyObject *__pyx_n_s_UNWEIGHTED;
 static PyObject *__pyx_n_s_UNWEIGHTED_CYCLES;
-static PyObject *__pyx_kp_s_Unknown_arc_type_r;
-static PyObject *__pyx_kp_s_Unknown_compose_filter_type_r;
-static PyObject *__pyx_kp_s_Unknown_determinization_type_r;
-static PyObject *__pyx_kp_s_Unknown_map_type_r;
-static PyObject *__pyx_kp_s_Unknown_queue_type_r;
-static PyObject *__pyx_kp_s_Unknown_random_arc_selection_typ;
-static PyObject *__pyx_kp_s_Unknown_replace_label_type_r;
-static PyObject *__pyx_kp_s_Unknown_sort_type_r;
+static PyObject *__pyx_kp_u_Unknown_arc_type_r;
+static PyObject *__pyx_kp_u_Unknown_compose_filter_type_r;
+static PyObject *__pyx_kp_u_Unknown_determinization_type_r;
+static PyObject *__pyx_kp_u_Unknown_map_type_r;
+static PyObject *__pyx_kp_u_Unknown_queue_type_r;
+static PyObject *__pyx_kp_u_Unknown_random_arc_selection_typ;
+static PyObject *__pyx_kp_u_Unknown_replace_label_type_r;
+static PyObject *__pyx_kp_u_Unknown_sort_type_r;
 static PyObject *__pyx_n_s_ValueError;
 static PyObject *__pyx_n_s_WEIGHTED;
 static PyObject *__pyx_n_s_WEIGHTED_CYCLES;
 static PyObject *__pyx_n_s_WEIGHT_INVARIANT_PROPERTIES;
-static PyObject *__pyx_kp_s_Weight_at_0x_x;
-static PyObject *__pyx_kp_s_Weight_type_not_found;
-static PyObject *__pyx_kp_s_Write_failed_r;
-static PyObject *__pyx_kp_s_Write_to_string_failed;
+static PyObject *__pyx_n_s_Weight;
+static PyObject *__pyx_kp_u_Weight_at_0x_x;
+static PyObject *__pyx_kp_u_Weight_type_not_found;
+static PyObject *__pyx_kp_u_Write_failed_r;
+static PyObject *__pyx_kp_u_Write_to_string_failed;
 static PyObject *__pyx_n_s_Zero;
-static PyObject *__pyx_kp_b__24;
+static PyObject *__pyx_kp_b__10;
 static PyObject *__pyx_n_s_acceptor;
 static PyObject *__pyx_n_s_add;
 static PyObject *__pyx_n_s_add_state;
@@ -3403,7 +3545,6 @@ static PyObject *__pyx_n_s_allow_nondet;
 static PyObject *__pyx_n_s_arc;
 static PyObject *__pyx_n_s_arc_type;
 static PyObject *__pyx_n_s_arcs;
-static PyObject *__pyx_n_s_atexit;
 static PyObject *__pyx_n_s_attach_new_isymbols;
 static PyObject *__pyx_n_s_attach_new_osymbols;
 static PyObject *__pyx_n_b_auto;
@@ -3418,11 +3559,10 @@ static PyObject *__pyx_n_s_communicate;
 static PyObject *__pyx_n_s_compile;
 static PyObject *__pyx_n_s_compose_filter;
 static PyObject *__pyx_n_s_connect;
-static PyObject *__pyx_kp_s_const_EncodeMapper_SymbolTable;
-static PyObject *__pyx_kp_s_const_Fst_SymbolTable_r_at_0x_x;
+static PyObject *__pyx_kp_u_const_EncodeMapper_SymbolTable;
+static PyObject *__pyx_kp_u_const_Fst_SymbolTable_r_at_0x_x;
 static PyObject *__pyx_n_s_copy;
 static PyObject *__pyx_n_s_create;
-static PyObject *__pyx_n_s_decode;
 static PyObject *__pyx_n_b_default;
 static PyObject *__pyx_n_s_delta;
 static PyObject *__pyx_n_s_det_type;
@@ -3430,7 +3570,7 @@ static PyObject *__pyx_n_s_distance;
 static PyObject *__pyx_n_s_divide;
 static PyObject *__pyx_n_s_doc;
 static PyObject *__pyx_n_s_done;
-static PyObject *__pyx_n_s_dot;
+static PyObject *__pyx_n_u_dot;
 static PyObject *__pyx_n_s_draw;
 static PyObject *__pyx_n_s_encode;
 static PyObject *__pyx_n_s_encode_labels;
@@ -3446,7 +3586,6 @@ static PyObject *__pyx_n_s_flags;
 static PyObject *__pyx_n_s_float_format;
 static PyObject *__pyx_n_s_fontsize;
 static PyObject *__pyx_n_s_format;
-static PyObject *__pyx_n_s_fst_error_fatal_old;
 static PyObject *__pyx_n_s_fst_type;
 static PyObject *__pyx_n_b_functional;
 static PyObject *__pyx_n_b_g;
@@ -3469,7 +3608,6 @@ static PyObject *__pyx_n_s_input_symbols;
 static PyObject *__pyx_n_s_input_table;
 static PyObject *__pyx_n_s_ipairs;
 static PyObject *__pyx_n_s_isymbols;
-static PyObject *__pyx_n_s_kNoSymbol;
 static PyObject *__pyx_n_s_keep_isymbols;
 static PyObject *__pyx_n_s_keep_osymbols;
 static PyObject *__pyx_n_s_keep_state_numbering;
@@ -3534,23 +3672,21 @@ static PyObject *__pyx_n_s_qualname;
 static PyObject *__pyx_n_s_queue_type;
 static PyObject *__pyx_n_s_ranksep;
 static PyObject *__pyx_n_s_read;
+static PyObject *__pyx_n_s_read_Fst_from_string;
+static PyObject *__pyx_n_s_read_SymbolTable_from_string;
 static PyObject *__pyx_n_s_read_from_string;
-static PyObject *__pyx_n_s_read_from_string_2;
 static PyObject *__pyx_n_s_read_fst;
 static PyObject *__pyx_n_s_read_text;
 static PyObject *__pyx_n_s_reduce;
 static PyObject *__pyx_n_s_reduce_cython;
 static PyObject *__pyx_n_s_reduce_ex;
-static PyObject *__pyx_n_s_register;
 static PyObject *__pyx_n_s_remove_common_affix;
 static PyObject *__pyx_n_s_remove_total_weight;
 static PyObject *__pyx_n_s_require_superinitial;
 static PyObject *__pyx_n_s_reset;
-static PyObject *__pyx_n_s_reset_fst_error_fatal;
 static PyObject *__pyx_n_s_result;
 static PyObject *__pyx_n_s_return_arc_labeling;
 static PyObject *__pyx_n_s_return_label;
-static PyObject *__pyx_n_s_returncode;
 static PyObject *__pyx_n_s_reverse;
 static PyObject *__pyx_n_s_rhs;
 static PyObject *__pyx_n_s_seed;
@@ -3560,14 +3696,9 @@ static PyObject *__pyx_kp_s_self__aiter_self__fst_cannot_be;
 static PyObject *__pyx_kp_s_self__aiter_self__mfst_cannot_be;
 static PyObject *__pyx_kp_s_self__arc_cannot_be_converted_to;
 static PyObject *__pyx_kp_s_self__encoder_cannot_be_converte;
-static PyObject *__pyx_kp_s_self__encoder_self__table_cannot;
 static PyObject *__pyx_kp_s_self__fst_self__siter_cannot_be;
-static PyObject *__pyx_kp_s_self__fst_self__table_cannot_be;
-static PyObject *__pyx_kp_s_self__mfst_self__table_cannot_be;
 static PyObject *__pyx_kp_s_self__reader_cannot_be_converted;
 static PyObject *__pyx_kp_s_self__siter_self__table_cannot_b;
-static PyObject *__pyx_kp_s_self__smart_table_self__table_ca;
-static PyObject *__pyx_kp_s_self__table_cannot_be_converted;
 static PyObject *__pyx_kp_s_self__weight_cannot_be_converted;
 static PyObject *__pyx_kp_s_self__writer_cannot_be_converted;
 static PyObject *__pyx_n_s_set_flags;
@@ -3586,7 +3717,6 @@ static PyObject *__pyx_n_s_start;
 static PyObject *__pyx_n_s_state;
 static PyObject *__pyx_n_s_states;
 static PyObject *__pyx_n_s_staticmethod;
-static PyObject *__pyx_n_s_stderr;
 static PyObject *__pyx_n_s_stdin;
 static PyObject *__pyx_n_s_stdout;
 static PyObject *__pyx_n_s_subprocess;
@@ -3605,8 +3735,8 @@ static PyObject *__pyx_n_b_uniform;
 static PyObject *__pyx_n_s_unique;
 static PyObject *__pyx_n_s_unknown_isymbol;
 static PyObject *__pyx_n_s_unknown_osymbol;
-static PyObject *__pyx_kp_b_unspecified;
-static PyObject *__pyx_n_s_utf8;
+static PyObject *__pyx_kp_u_unspecified;
+static PyObject *__pyx_n_u_utf8;
 static PyObject *__pyx_n_s_value;
 static PyObject *__pyx_n_b_vector;
 static PyObject *__pyx_n_s_verify;
@@ -3640,43 +3770,34 @@ static PyObject *__pyx_pf_9pywrapfst_4divide(CYTHON_UNUSED PyObject *__pyx_self,
 static PyObject *__pyx_pf_9pywrapfst_6power(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst_Weight *__pyx_v_w, size_t __pyx_v_n); /* proto */
 static int __pyx_pf_9pywrapfst_12_SymbolTable___init__(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_2__iter__(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_4available_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_6checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_8copy(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_12get_nth_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, Py_ssize_t __pyx_v_pos); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_14labeled_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_16member(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key); /* proto */
-static int __pyx_pf_9pywrapfst_12_SymbolTable_18__contains__(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_20name(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_22num_symbols(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_24write(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_26write_text(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_28__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_30__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_4__reduce__(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_6available_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_8checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10copy(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_12find(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_14get_nth_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, Py_ssize_t __pyx_v_pos); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_16labeled_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_18member(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key); /* proto */
+static int __pyx_pf_9pywrapfst_12_SymbolTable_20__contains__(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_22name(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_24num_symbols(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_26write(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_28write_text(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_30write_to_string(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable___repr__(struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable_2__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable_4__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable___repr__(struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable_2__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable_4__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_add_symbol(struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self, PyObject *__pyx_v_symbol, __pyx_t_10basictypes_int64 __pyx_v_key); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_2add_table(struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_4set_name(struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self, PyObject *__pyx_v_new_name); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_6__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_8__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable___repr__(struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable_2__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable_4__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_11SymbolTable___repr__(struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_self); /* proto */
 static int __pyx_pf_9pywrapfst_11SymbolTable_2__init__(struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_self, PyObject *__pyx_v_name); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_4read(CYTHON_UNUSED PyTypeObject *__pyx_v_cls, PyObject *__pyx_v_filename); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_6read_text(CYTHON_UNUSED PyTypeObject *__pyx_v_cls, PyObject *__pyx_v_filename, bool __pyx_v_allow_negative_labels); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_8read_fst(CYTHON_UNUSED PyTypeObject *__pyx_v_cls, PyObject *__pyx_v_filename, bool __pyx_v_input_table); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_10__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_12__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_8compact_symbol_table(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_10merge_symbol_table(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_lhs, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_rhs); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_8_read_SymbolTable_from_string(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_state); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_10compact_symbol_table(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_12merge_symbol_table(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_lhs, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_rhs); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator___repr__(struct __pyx_obj_9pywrapfst_SymbolTableIterator *__pyx_v_self); /* proto */
 static int __pyx_pf_9pywrapfst_19SymbolTableIterator_2__init__(struct __pyx_obj_9pywrapfst_SymbolTableIterator *__pyx_v_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_4__iter__(struct __pyx_obj_9pywrapfst_SymbolTableIterator *__pyx_v_self); /* proto */
@@ -3702,10 +3823,10 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_20weight_type(struct __pyx_o
 static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_22__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_EncodeMapper *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_24__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_EncodeMapper *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_4_Fst__repr_svg_(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_4_Fst_2__repr__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
-static int __pyx_pf_9pywrapfst_4_Fst_4__init__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_4_Fst_6__str__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_4_Fst_8__reduce__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
+static int __pyx_pf_9pywrapfst_4_Fst_2__init__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_4_Fst_4__reduce__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_4_Fst_6__repr__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_4_Fst_8__str__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_4_Fst_10arc_type(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_4_Fst_12arcs(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, __pyx_t_10basictypes_int64 __pyx_v_state); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_4_Fst_14copy(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self); /* proto */
@@ -3757,8 +3878,8 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_56set_properties(struct __pyx
 static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_58set_start(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self, __pyx_t_10basictypes_int64 __pyx_v_state); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_60topsort(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_62union(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_12_read(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_14_read_from_string(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_state); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_14_read(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_16_read_Fst_from_string(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_state); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_3Fst___new__(CYTHON_UNUSED PyObject *__pyx_self, CYTHON_UNUSED PyObject *__pyx_v_cls, PyObject *__pyx_v_arc_type); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_3Fst_2read(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_filename); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_3Fst_4read_from_string(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_state); /* proto */
@@ -3812,27 +3933,27 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_12reset(struct __pyx_obj_9p
 static PyObject *__pyx_pf_9pywrapfst_13StateIterator_14value(struct __pyx_obj_9pywrapfst_StateIterator *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_13StateIterator_16__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_StateIterator *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_13StateIterator_18__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_StateIterator *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_16arcmap(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, PyObject *__pyx_v_map_type, double __pyx_v_power, PyObject *__pyx_v_weight); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_18compose(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_20convert(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, PyObject *__pyx_v_fst_type); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_22determinize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, PyObject *__pyx_v_det_type, __pyx_t_10basictypes_int64 __pyx_v_nstate, __pyx_t_10basictypes_int64 __pyx_v_subsequential_label, PyObject *__pyx_v_weight, bool __pyx_v_increment_subsequential_label); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_24difference(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_26disambiguate(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, __pyx_t_10basictypes_int64 __pyx_v_subsequential_label, PyObject *__pyx_v_weight); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_28epsnormalize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, bool __pyx_v_eps_norm_output); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_30equal(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_32equivalent(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_34intersect(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_36isomorphic(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_38prune(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_weight); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_40push(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, bool __pyx_v_push_weights, bool __pyx_v_push_labels, bool __pyx_v_remove_common_affix, bool __pyx_v_remove_total_weight, bool __pyx_v_to_final); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_42randequivalent(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, __pyx_t_10basictypes_int32 __pyx_v_npath, float __pyx_v_delta, time_t __pyx_v_seed, PyObject *__pyx_v_select, __pyx_t_10basictypes_int32 __pyx_v_max_length); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_44randgen(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, __pyx_t_10basictypes_int32 __pyx_v_npath, time_t __pyx_v_seed, PyObject *__pyx_v_select, __pyx_t_10basictypes_int32 __pyx_v_max_length, bool __pyx_v_weighted, bool __pyx_v_remove_total_weight); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_46replace(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_pairs, PyObject *__pyx_v_call_arc_labeling, PyObject *__pyx_v_return_arc_labeling, bool __pyx_v_epsilon_on_replace, __pyx_t_10basictypes_int64 __pyx_v_return_label); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_48reverse(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, bool __pyx_v_require_superinitial); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_50shortestdistance(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_queue_type, bool __pyx_v_reverse); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_52shortestpath(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int32 __pyx_v_nshortest, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_queue_type, bool __pyx_v_unique, PyObject *__pyx_v_weight); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_54statemap(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, PyObject *__pyx_v_map_type); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_56synchronize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_18arcmap(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, PyObject *__pyx_v_map_type, double __pyx_v_power, PyObject *__pyx_v_weight); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_20compose(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_22convert(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, PyObject *__pyx_v_fst_type); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_24determinize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, PyObject *__pyx_v_det_type, __pyx_t_10basictypes_int64 __pyx_v_nstate, __pyx_t_10basictypes_int64 __pyx_v_subsequential_label, PyObject *__pyx_v_weight, bool __pyx_v_increment_subsequential_label); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_26difference(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_28disambiguate(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, __pyx_t_10basictypes_int64 __pyx_v_subsequential_label, PyObject *__pyx_v_weight); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_30epsnormalize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, bool __pyx_v_eps_norm_output); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_32equal(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_34equivalent(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_36intersect(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_38isomorphic(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_40prune(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_weight); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_42push(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, bool __pyx_v_push_weights, bool __pyx_v_push_labels, bool __pyx_v_remove_common_affix, bool __pyx_v_remove_total_weight, bool __pyx_v_to_final); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_44randequivalent(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, __pyx_t_10basictypes_int32 __pyx_v_npath, float __pyx_v_delta, time_t __pyx_v_seed, PyObject *__pyx_v_select, __pyx_t_10basictypes_int32 __pyx_v_max_length); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_46randgen(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, __pyx_t_10basictypes_int32 __pyx_v_npath, time_t __pyx_v_seed, PyObject *__pyx_v_select, __pyx_t_10basictypes_int32 __pyx_v_max_length, bool __pyx_v_weighted, bool __pyx_v_remove_total_weight); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_48replace(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_pairs, PyObject *__pyx_v_call_arc_labeling, PyObject *__pyx_v_return_arc_labeling, bool __pyx_v_epsilon_on_replace, __pyx_t_10basictypes_int64 __pyx_v_return_label); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_50reverse(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, bool __pyx_v_require_superinitial); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_52shortestdistance(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_queue_type, bool __pyx_v_reverse); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_54shortestpath(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int32 __pyx_v_nshortest, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_queue_type, bool __pyx_v_unique, PyObject *__pyx_v_weight); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_56statemap(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, PyObject *__pyx_v_map_type); /* proto */
+static PyObject *__pyx_pf_9pywrapfst_58synchronize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst); /* proto */
 static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_Compiler *__pyx_v_self, std::string __pyx_v_fst_type, std::string __pyx_v_arc_type, struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_isymbols, struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_osymbols, struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_ssymbols, bool __pyx_v_acceptor, bool __pyx_v_keep_isymbols, bool __pyx_v_keep_osymbols, bool __pyx_v_keep_state_numbering, bool __pyx_v_allow_negative_labels); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_8Compiler_2compile(struct __pyx_obj_9pywrapfst_Compiler *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_8Compiler_4write(struct __pyx_obj_9pywrapfst_Compiler *__pyx_v_self, PyObject *__pyx_v_expression); /* proto */
@@ -3863,7 +3984,6 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_12far_type(struct __pyx_obj_9pyw
 static int __pyx_pf_9pywrapfst_9FarWriter_14__setitem__(struct __pyx_obj_9pywrapfst_FarWriter *__pyx_v_self, PyObject *__pyx_v_key, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_fst); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_9FarWriter_16__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_FarWriter *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9pywrapfst_9FarWriter_18__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_FarWriter *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
-static PyObject *__pyx_pf_9pywrapfst_58_reset_fst_error_fatal(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
 static PyObject *__pyx_tp_new_9pywrapfst_Weight(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9pywrapfst__SymbolTable(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9pywrapfst__EncodeMapperSymbolTable(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
@@ -3882,83 +4002,58 @@ static PyObject *__pyx_tp_new_9pywrapfst_StateIterator(PyTypeObject *t, PyObject
 static PyObject *__pyx_tp_new_9pywrapfst_Compiler(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9pywrapfst_FarReader(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9pywrapfst_FarWriter(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
-static PyObject *__pyx_int_0;
-static PyObject *__pyx_int_neg_1;
-static __pyx_t_10basictypes_int64 __pyx_k__13;
+static __pyx_t_10basictypes_int64 __pyx_k__3;
+static float __pyx_k__11;
+static float __pyx_k__12;
+static float __pyx_k__13;
+static __pyx_t_10basictypes_int64 __pyx_k__14;
+static float __pyx_k__15;
+static __pyx_t_10basictypes_int64 __pyx_k__16;
+static float __pyx_k__17;
+static float __pyx_k__18;
+static __pyx_t_10basictypes_int64 __pyx_k__19;
+static float __pyx_k__20;
+static __pyx_t_10basictypes_int64 __pyx_k__21;
+static float __pyx_k__22;
+static float __pyx_k__31;
+static float __pyx_k__32;
+static float __pyx_k__33;
+static __pyx_t_10basictypes_int64 __pyx_k__34;
 static float __pyx_k__35;
-static float __pyx_k__36;
+static __pyx_t_10basictypes_int64 __pyx_k__36;
 static float __pyx_k__37;
-static __pyx_t_10basictypes_int64 __pyx_k__38;
+static float __pyx_k__38;
 static float __pyx_k__39;
-static __pyx_t_10basictypes_int64 __pyx_k__40;
-static float __pyx_k__41;
+static float __pyx_k__40;
+static __pyx_t_10basictypes_int64 __pyx_k__41;
 static float __pyx_k__42;
-static __pyx_t_10basictypes_int64 __pyx_k__46;
-static float __pyx_k__47;
-static __pyx_t_10basictypes_int64 __pyx_k__48;
-static float __pyx_k__49;
-static float __pyx_k__67;
-static float __pyx_k__68;
-static float __pyx_k__69;
-static __pyx_t_10basictypes_int64 __pyx_k__70;
-static float __pyx_k__71;
-static __pyx_t_10basictypes_int64 __pyx_k__72;
-static float __pyx_k__73;
-static float __pyx_k__74;
-static float __pyx_k__75;
-static float __pyx_k__76;
-static __pyx_t_10basictypes_int64 __pyx_k__77;
-static float __pyx_k__78;
-static float __pyx_k__79;
-static __pyx_t_10basictypes_int32 __pyx_k__80;
-static __pyx_t_10basictypes_int32 __pyx_k__81;
-static float __pyx_k__82;
-static __pyx_t_10basictypes_int64 __pyx_k__83;
-static float __pyx_k__84;
-static __pyx_t_10basictypes_int64 __pyx_k__85;
-static float __pyx_k__86;
-static __pyx_t_10basictypes_int64 __pyx_k__87;
-static std::string __pyx_k__88;
-static std::string __pyx_k__89;
+static float __pyx_k__43;
+static __pyx_t_10basictypes_int32 __pyx_k__44;
+static __pyx_t_10basictypes_int32 __pyx_k__45;
+static float __pyx_k__46;
+static __pyx_t_10basictypes_int64 __pyx_k__47;
+static float __pyx_k__48;
+static __pyx_t_10basictypes_int64 __pyx_k__49;
+static float __pyx_k__50;
+static __pyx_t_10basictypes_int64 __pyx_k__51;
+static std::string __pyx_k__52;
+static std::string __pyx_k__53;
 static PyObject *__pyx_tuple_;
 static PyObject *__pyx_tuple__2;
-static PyObject *__pyx_tuple__3;
 static PyObject *__pyx_tuple__4;
 static PyObject *__pyx_tuple__5;
 static PyObject *__pyx_tuple__6;
 static PyObject *__pyx_tuple__7;
 static PyObject *__pyx_tuple__8;
 static PyObject *__pyx_tuple__9;
-static PyObject *__pyx_tuple__10;
-static PyObject *__pyx_tuple__11;
-static PyObject *__pyx_tuple__12;
-static PyObject *__pyx_tuple__14;
-static PyObject *__pyx_tuple__15;
-static PyObject *__pyx_tuple__16;
-static PyObject *__pyx_tuple__17;
-static PyObject *__pyx_tuple__18;
-static PyObject *__pyx_tuple__19;
-static PyObject *__pyx_tuple__20;
-static PyObject *__pyx_tuple__21;
-static PyObject *__pyx_tuple__22;
 static PyObject *__pyx_tuple__23;
+static PyObject *__pyx_tuple__24;
 static PyObject *__pyx_tuple__25;
 static PyObject *__pyx_tuple__26;
 static PyObject *__pyx_tuple__27;
 static PyObject *__pyx_tuple__28;
 static PyObject *__pyx_tuple__29;
 static PyObject *__pyx_tuple__30;
-static PyObject *__pyx_tuple__31;
-static PyObject *__pyx_tuple__32;
-static PyObject *__pyx_tuple__33;
-static PyObject *__pyx_tuple__34;
-static PyObject *__pyx_tuple__43;
-static PyObject *__pyx_tuple__44;
-static PyObject *__pyx_tuple__45;
-static PyObject *__pyx_tuple__50;
-static PyObject *__pyx_tuple__51;
-static PyObject *__pyx_tuple__52;
-static PyObject *__pyx_tuple__53;
 static PyObject *__pyx_tuple__54;
 static PyObject *__pyx_tuple__55;
 static PyObject *__pyx_tuple__56;
@@ -3966,43 +4061,26 @@ static PyObject *__pyx_tuple__57;
 static PyObject *__pyx_tuple__58;
 static PyObject *__pyx_tuple__59;
 static PyObject *__pyx_tuple__60;
-static PyObject *__pyx_tuple__61;
 static PyObject *__pyx_tuple__62;
-static PyObject *__pyx_tuple__63;
 static PyObject *__pyx_tuple__64;
-static PyObject *__pyx_tuple__65;
 static PyObject *__pyx_tuple__66;
-static PyObject *__pyx_tuple__90;
-static PyObject *__pyx_tuple__91;
-static PyObject *__pyx_tuple__92;
-static PyObject *__pyx_tuple__93;
-static PyObject *__pyx_tuple__94;
-static PyObject *__pyx_tuple__95;
-static PyObject *__pyx_tuple__96;
-static PyObject *__pyx_tuple__97;
-static PyObject *__pyx_tuple__98;
-static PyObject *__pyx_tuple__99;
-static PyObject *__pyx_tuple__101;
-static PyObject *__pyx_tuple__103;
-static PyObject *__pyx_tuple__105;
-static PyObject *__pyx_tuple__107;
-static PyObject *__pyx_tuple__108;
-static PyObject *__pyx_tuple__110;
-static PyObject *__pyx_tuple__111;
-static PyObject *__pyx_tuple__113;
-static PyObject *__pyx_tuple__115;
-static PyObject *__pyx_codeobj__100;
-static PyObject *__pyx_codeobj__102;
-static PyObject *__pyx_codeobj__104;
-static PyObject *__pyx_codeobj__106;
-static PyObject *__pyx_codeobj__109;
-static PyObject *__pyx_codeobj__112;
-static PyObject *__pyx_codeobj__114;
-static PyObject *__pyx_codeobj__116;
-static PyObject *__pyx_codeobj__117;
+static PyObject *__pyx_tuple__68;
+static PyObject *__pyx_tuple__69;
+static PyObject *__pyx_tuple__71;
+static PyObject *__pyx_tuple__72;
+static PyObject *__pyx_tuple__74;
+static PyObject *__pyx_tuple__76;
+static PyObject *__pyx_codeobj__61;
+static PyObject *__pyx_codeobj__63;
+static PyObject *__pyx_codeobj__65;
+static PyObject *__pyx_codeobj__67;
+static PyObject *__pyx_codeobj__70;
+static PyObject *__pyx_codeobj__73;
+static PyObject *__pyx_codeobj__75;
+static PyObject *__pyx_codeobj__77;
 /* Late includes */
 
-/* "pywrapfst.pyx":159
+/* "pywrapfst.pyx":144
  * 
  * 
  * cdef string tostring(data, encoding="utf8") except *:             # <<<<<<<<<<<<<<
@@ -4011,7 +4089,7 @@ static PyObject *__pyx_codeobj__117;
  */
 
 static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __pyx_opt_args_9pywrapfst_tostring *__pyx_optional_args) {
-  PyObject *__pyx_v_encoding = ((PyObject *)__pyx_n_s_utf8);
+  PyObject *__pyx_v_encoding = ((PyObject *)__pyx_n_u_utf8);
   std::string __pyx_r;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -4022,7 +4100,6 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
   PyObject *__pyx_t_8 = NULL;
-  PyObject *__pyx_t_9 = NULL;
   __Pyx_RefNannySetupContext("tostring", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -4030,7 +4107,7 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
     }
   }
 
-  /* "pywrapfst.pyx":180
+  /* "pywrapfst.pyx":165
  *   """
  *   # A Python bytestring can be implicitly cast to a C++ string.
  *   if isinstance(data, bytes):             # <<<<<<<<<<<<<<
@@ -4041,18 +4118,18 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
   __pyx_t_2 = (__pyx_t_1 != 0);
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":181
+    /* "pywrapfst.pyx":166
  *   # A Python bytestring can be implicitly cast to a C++ string.
  *   if isinstance(data, bytes):
  *     return data             # <<<<<<<<<<<<<<
  *   elif isinstance(data, unicode):
  *     return data.encode(encoding)
  */
-    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_v_data); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 181, __pyx_L1_error)
+    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_v_data); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 166, __pyx_L1_error)
     __pyx_r = __pyx_t_3;
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":180
+    /* "pywrapfst.pyx":165
  *   """
  *   # A Python bytestring can be implicitly cast to a C++ string.
  *   if isinstance(data, bytes):             # <<<<<<<<<<<<<<
@@ -4061,7 +4138,7 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
  */
   }
 
-  /* "pywrapfst.pyx":182
+  /* "pywrapfst.pyx":167
  *   if isinstance(data, bytes):
  *     return data
  *   elif isinstance(data, unicode):             # <<<<<<<<<<<<<<
@@ -4072,14 +4149,14 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
   __pyx_t_1 = (__pyx_t_2 != 0);
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":183
+    /* "pywrapfst.pyx":168
  *     return data
  *   elif isinstance(data, unicode):
  *     return data.encode(encoding)             # <<<<<<<<<<<<<<
  *   raise FstArgError("Cannot encode as string: {!r}".format(data))
  * 
  */
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_data, __pyx_n_s_encode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 183, __pyx_L1_error)
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_data, __pyx_n_s_encode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 168, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
@@ -4091,45 +4168,17 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
         __Pyx_DECREF_SET(__pyx_t_5, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_encoding); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 183, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_v_encoding};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 183, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_v_encoding};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 183, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else
-      #endif
-      {
-        __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 183, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_INCREF(__pyx_v_encoding);
-        __Pyx_GIVEREF(__pyx_v_encoding);
-        PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_v_encoding);
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 183, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      }
-    }
+    __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_6, __pyx_v_encoding) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_encoding);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 168, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_t_4); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 183, __pyx_L1_error)
+    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_t_4); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 168, __pyx_L1_error)
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __pyx_r = __pyx_t_3;
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":182
+    /* "pywrapfst.pyx":167
  *   if isinstance(data, bytes):
  *     return data
  *   elif isinstance(data, unicode):             # <<<<<<<<<<<<<<
@@ -4138,111 +4187,53 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
  */
   }
 
-  /* "pywrapfst.pyx":184
+  /* "pywrapfst.pyx":169
  *   elif isinstance(data, unicode):
  *     return data.encode(encoding)
  *   raise FstArgError("Cannot encode as string: {!r}".format(data))             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 184, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 169, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Cannot_encode_as_string_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 184, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Cannot_encode_as_string_r, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 169, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_7);
   __pyx_t_8 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
-    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_6);
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
+    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7);
     if (likely(__pyx_t_8)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
       __Pyx_INCREF(__pyx_t_8);
       __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_6, function);
-    }
-  }
-  if (!__pyx_t_8) {
-    __pyx_t_7 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_data); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 184, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_6)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_data};
-      __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 184, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __Pyx_GOTREF(__pyx_t_7);
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_data};
-      __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 184, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __Pyx_GOTREF(__pyx_t_7);
-    } else
-    #endif
-    {
-      __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 184, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_8); __pyx_t_8 = NULL;
-      __Pyx_INCREF(__pyx_v_data);
-      __Pyx_GIVEREF(__pyx_v_data);
-      PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_v_data);
-      __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_9, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 184, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+      __Pyx_DECREF_SET(__pyx_t_7, function);
     }
   }
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_6 = NULL;
+  __pyx_t_6 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_data);
+  __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+  if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 169, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+  __pyx_t_7 = NULL;
   if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
-    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
-    if (likely(__pyx_t_6)) {
+    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5);
+    if (likely(__pyx_t_7)) {
       PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-      __Pyx_INCREF(__pyx_t_6);
+      __Pyx_INCREF(__pyx_t_7);
       __Pyx_INCREF(function);
       __Pyx_DECREF_SET(__pyx_t_5, function);
     }
   }
-  if (!__pyx_t_6) {
-    __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_7); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 184, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __Pyx_GOTREF(__pyx_t_4);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_5)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_7};
-      __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 184, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_7};
-      __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 184, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 184, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_6); __pyx_t_6 = NULL;
-      __Pyx_GIVEREF(__pyx_t_7);
-      PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_t_7);
-      __pyx_t_7 = 0;
-      __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 184, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-    }
-  }
+  __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 169, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __Pyx_Raise(__pyx_t_4, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __PYX_ERR(0, 184, __pyx_L1_error)
+  __PYX_ERR(0, 169, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":159
+  /* "pywrapfst.pyx":144
  * 
  * 
  * cdef string tostring(data, encoding="utf8") except *:             # <<<<<<<<<<<<<<
@@ -4257,7 +4248,6 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
   __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
   __Pyx_AddTraceback("pywrapfst.tostring", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_pretend_to_initialize(&__pyx_r);
   __pyx_L0:;
@@ -4265,7 +4255,7 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":187
+/* "pywrapfst.pyx":172
  * 
  * 
  * cdef string weight_tostring(data, encoding="utf8") except *:             # <<<<<<<<<<<<<<
@@ -4274,7 +4264,7 @@ static std::string __pyx_f_9pywrapfst_tostring(PyObject *__pyx_v_data, struct __
  */
 
 static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, struct __pyx_opt_args_9pywrapfst_weight_tostring *__pyx_optional_args) {
-  PyObject *__pyx_v_encoding = ((PyObject *)__pyx_n_s_utf8);
+  PyObject *__pyx_v_encoding = ((PyObject *)__pyx_n_u_utf8);
   std::string __pyx_r;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -4285,7 +4275,6 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
   PyObject *__pyx_t_8 = NULL;
-  PyObject *__pyx_t_9 = NULL;
   __Pyx_RefNannySetupContext("weight_tostring", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -4293,7 +4282,7 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
     }
   }
 
-  /* "pywrapfst.pyx":211
+  /* "pywrapfst.pyx":196
  *   """
  *   # A Python bytestring can be implicitly cast to a C++ string.
  *   if isinstance(data, bytes):             # <<<<<<<<<<<<<<
@@ -4304,18 +4293,18 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
   __pyx_t_2 = (__pyx_t_1 != 0);
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":212
+    /* "pywrapfst.pyx":197
  *   # A Python bytestring can be implicitly cast to a C++ string.
  *   if isinstance(data, bytes):
  *     return data             # <<<<<<<<<<<<<<
  *   elif isinstance(data, unicode):
  *     return data.encode(encoding)
  */
-    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_v_data); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 212, __pyx_L1_error)
+    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_v_data); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 197, __pyx_L1_error)
     __pyx_r = __pyx_t_3;
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":211
+    /* "pywrapfst.pyx":196
  *   """
  *   # A Python bytestring can be implicitly cast to a C++ string.
  *   if isinstance(data, bytes):             # <<<<<<<<<<<<<<
@@ -4324,7 +4313,7 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
  */
   }
 
-  /* "pywrapfst.pyx":213
+  /* "pywrapfst.pyx":198
  *   if isinstance(data, bytes):
  *     return data
  *   elif isinstance(data, unicode):             # <<<<<<<<<<<<<<
@@ -4335,14 +4324,14 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
   __pyx_t_1 = (__pyx_t_2 != 0);
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":214
+    /* "pywrapfst.pyx":199
  *     return data
  *   elif isinstance(data, unicode):
  *     return data.encode(encoding)             # <<<<<<<<<<<<<<
  *   elif isinstance(data, numbers.Number):
  *     return str(data).encode(encoding)
  */
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_data, __pyx_n_s_encode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 214, __pyx_L1_error)
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_data, __pyx_n_s_encode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 199, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
@@ -4354,45 +4343,17 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
         __Pyx_DECREF_SET(__pyx_t_5, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_encoding); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 214, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_v_encoding};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 214, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_v_encoding};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 214, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else
-      #endif
-      {
-        __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 214, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_INCREF(__pyx_v_encoding);
-        __Pyx_GIVEREF(__pyx_v_encoding);
-        PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_v_encoding);
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 214, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      }
-    }
+    __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_6, __pyx_v_encoding) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_encoding);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 199, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_t_4); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 214, __pyx_L1_error)
+    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_t_4); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 199, __pyx_L1_error)
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __pyx_r = __pyx_t_3;
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":213
+    /* "pywrapfst.pyx":198
  *   if isinstance(data, bytes):
  *     return data
  *   elif isinstance(data, unicode):             # <<<<<<<<<<<<<<
@@ -4401,84 +4362,56 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
  */
   }
 
-  /* "pywrapfst.pyx":215
+  /* "pywrapfst.pyx":200
  *   elif isinstance(data, unicode):
  *     return data.encode(encoding)
  *   elif isinstance(data, numbers.Number):             # <<<<<<<<<<<<<<
  *     return str(data).encode(encoding)
  *   raise FstArgError("Cannot encode as string: {!r}".format(data))
  */
-  __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_numbers); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 215, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_numbers); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 200, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_Number); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 215, __pyx_L1_error)
+  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_Number); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 200, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_5);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_1 = PyObject_IsInstance(__pyx_v_data, __pyx_t_5); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(0, 215, __pyx_L1_error)
+  __pyx_t_1 = PyObject_IsInstance(__pyx_v_data, __pyx_t_5); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(0, 200, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __pyx_t_2 = (__pyx_t_1 != 0);
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":216
+    /* "pywrapfst.pyx":201
  *     return data.encode(encoding)
  *   elif isinstance(data, numbers.Number):
  *     return str(data).encode(encoding)             # <<<<<<<<<<<<<<
  *   raise FstArgError("Cannot encode as string: {!r}".format(data))
  * 
  */
-    __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyString_Type)), __pyx_v_data); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 216, __pyx_L1_error)
+    __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyUnicode_Type)), __pyx_v_data); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 201, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_encode); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 216, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_encode); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 201, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __pyx_t_4 = NULL;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
-      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_7);
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_6);
       if (likely(__pyx_t_4)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
         __Pyx_INCREF(__pyx_t_4);
         __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_7, function);
-      }
-    }
-    if (!__pyx_t_4) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_encoding); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 216, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_7)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_encoding};
-        __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 216, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_encoding};
-        __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 216, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      {
-        __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 216, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); __pyx_t_4 = NULL;
-        __Pyx_INCREF(__pyx_v_encoding);
-        __Pyx_GIVEREF(__pyx_v_encoding);
-        PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_v_encoding);
-        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_6, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 216, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+        __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_t_5); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 216, __pyx_L1_error)
+    __pyx_t_5 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_4, __pyx_v_encoding) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_encoding);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 201, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_t_5); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 201, __pyx_L1_error)
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __pyx_r = __pyx_t_3;
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":215
+    /* "pywrapfst.pyx":200
  *   elif isinstance(data, unicode):
  *     return data.encode(encoding)
  *   elif isinstance(data, numbers.Number):             # <<<<<<<<<<<<<<
@@ -4487,111 +4420,53 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
  */
   }
 
-  /* "pywrapfst.pyx":217
+  /* "pywrapfst.pyx":202
  *   elif isinstance(data, numbers.Number):
  *     return str(data).encode(encoding)
  *   raise FstArgError("Cannot encode as string: {!r}".format(data))             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_7 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 217, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 202, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Cannot_encode_as_string_r, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 202, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Cannot_encode_as_string_r, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 217, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
   __pyx_t_8 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
-    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_4);
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
+    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7);
     if (likely(__pyx_t_8)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_8);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_4, function);
-    }
-  }
-  if (!__pyx_t_8) {
-    __pyx_t_6 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_data); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 217, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_data};
-      __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __Pyx_GOTREF(__pyx_t_6);
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_data};
-      __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __Pyx_GOTREF(__pyx_t_6);
-    } else
-    #endif
-    {
-      __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_8); __pyx_t_8 = NULL;
-      __Pyx_INCREF(__pyx_v_data);
-      __Pyx_GIVEREF(__pyx_v_data);
-      PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_v_data);
-      __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_9, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-    }
-  }
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_7);
-    if (likely(__pyx_t_4)) {
       PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
-      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_8);
       __Pyx_INCREF(function);
       __Pyx_DECREF_SET(__pyx_t_7, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 217, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_GOTREF(__pyx_t_5);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_7)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_6};
-      __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_6};
-      __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_6);
-      PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_t_6);
-      __pyx_t_6 = 0;
-      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_9, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+  __pyx_t_4 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_data);
+  __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+  if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 202, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+  __pyx_t_7 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) {
+    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6);
+    if (likely(__pyx_t_7)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
+      __Pyx_INCREF(__pyx_t_7);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_6, function);
     }
   }
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+  __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 202, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
   __Pyx_Raise(__pyx_t_5, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __PYX_ERR(0, 217, __pyx_L1_error)
+  __PYX_ERR(0, 202, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":187
+  /* "pywrapfst.pyx":172
  * 
  * 
  * cdef string weight_tostring(data, encoding="utf8") except *:             # <<<<<<<<<<<<<<
@@ -4606,7 +4481,6 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
   __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
   __Pyx_AddTraceback("pywrapfst.weight_tostring", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_pretend_to_initialize(&__pyx_r);
   __pyx_L0:;
@@ -4614,7 +4488,7 @@ static std::string __pyx_f_9pywrapfst_weight_tostring(PyObject *__pyx_v_data, st
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":220
+/* "pywrapfst.pyx":205
  * 
  * 
  * cdef fst.ComposeFilter _get_compose_filter(             # <<<<<<<<<<<<<<
@@ -4633,10 +4507,9 @@ static enum fst::ComposeFilter __pyx_f_9pywrapfst__get_compose_filter(std::strin
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_get_compose_filter", 0);
 
-  /* "pywrapfst.pyx":241
+  /* "pywrapfst.pyx":226
  *   """
  *   cdef fst.ComposeFilter compose_filter_enum
  *   if not fst.GetComposeFilter(compose_filter, addr(compose_filter_enum)):             # <<<<<<<<<<<<<<
@@ -4646,26 +4519,26 @@ static enum fst::ComposeFilter __pyx_f_9pywrapfst__get_compose_filter(std::strin
   __pyx_t_1 = ((!(fst::script::GetComposeFilter(__pyx_v_compose_filter, (&__pyx_v_compose_filter_enum)) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":242
+    /* "pywrapfst.pyx":227
  *   cdef fst.ComposeFilter compose_filter_enum
  *   if not fst.GetComposeFilter(compose_filter, addr(compose_filter_enum)):
  *     raise FstArgError("Unknown compose filter type: {!r}".format(             # <<<<<<<<<<<<<<
  *         compose_filter))
  *   return compose_filter_enum
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 242, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 227, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_compose_filter_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 242, __pyx_L1_error)
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_compose_filter_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 227, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
 
-    /* "pywrapfst.pyx":243
+    /* "pywrapfst.pyx":228
  *   if not fst.GetComposeFilter(compose_filter, addr(compose_filter_enum)):
  *     raise FstArgError("Unknown compose filter type: {!r}".format(
  *         compose_filter))             # <<<<<<<<<<<<<<
  *   return compose_filter_enum
  * 
  */
-    __pyx_t_6 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_compose_filter); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 243, __pyx_L1_error)
+    __pyx_t_6 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_compose_filter); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 228, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
@@ -4677,41 +4550,11 @@ static enum fst::ComposeFilter __pyx_f_9pywrapfst__get_compose_filter(std::strin
         __Pyx_DECREF_SET(__pyx_t_5, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 242, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 242, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 242, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 242, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_6);
-        __pyx_t_6 = 0;
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 242, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 227, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __pyx_t_5 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
@@ -4723,47 +4566,17 @@ static enum fst::ComposeFilter __pyx_f_9pywrapfst__get_compose_filter(std::strin
         __Pyx_DECREF_SET(__pyx_t_3, function);
       }
     }
-    if (!__pyx_t_5) {
-      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 242, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_2);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 242, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 242, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 242, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_4);
-        __pyx_t_4 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 242, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 227, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 242, __pyx_L1_error)
+    __PYX_ERR(0, 227, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":241
+    /* "pywrapfst.pyx":226
  *   """
  *   cdef fst.ComposeFilter compose_filter_enum
  *   if not fst.GetComposeFilter(compose_filter, addr(compose_filter_enum)):             # <<<<<<<<<<<<<<
@@ -4772,7 +4585,7 @@ static enum fst::ComposeFilter __pyx_f_9pywrapfst__get_compose_filter(std::strin
  */
   }
 
-  /* "pywrapfst.pyx":244
+  /* "pywrapfst.pyx":229
  *     raise FstArgError("Unknown compose filter type: {!r}".format(
  *         compose_filter))
  *   return compose_filter_enum             # <<<<<<<<<<<<<<
@@ -4782,7 +4595,7 @@ static enum fst::ComposeFilter __pyx_f_9pywrapfst__get_compose_filter(std::strin
   __pyx_r = __pyx_v_compose_filter_enum;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":220
+  /* "pywrapfst.pyx":205
  * 
  * 
  * cdef fst.ComposeFilter _get_compose_filter(             # <<<<<<<<<<<<<<
@@ -4798,7 +4611,6 @@ static enum fst::ComposeFilter __pyx_f_9pywrapfst__get_compose_filter(std::strin
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._get_compose_filter", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = (enum fst::ComposeFilter) 0;
   __pyx_L0:;
@@ -4806,7 +4618,7 @@ static enum fst::ComposeFilter __pyx_f_9pywrapfst__get_compose_filter(std::strin
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":247
+/* "pywrapfst.pyx":232
  * 
  * 
  * cdef fst.DeterminizeType _get_determinize_type(const string &det_type) except *:             # <<<<<<<<<<<<<<
@@ -4825,10 +4637,9 @@ static enum fst::DeterminizeType __pyx_f_9pywrapfst__get_determinize_type(std::s
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_get_determinize_type", 0);
 
-  /* "pywrapfst.pyx":263
+  /* "pywrapfst.pyx":248
  *   """
  *   cdef fst.DeterminizeType det_type_enum
  *   if not fst.GetDeterminizeType(det_type, addr(det_type_enum)):             # <<<<<<<<<<<<<<
@@ -4838,18 +4649,18 @@ static enum fst::DeterminizeType __pyx_f_9pywrapfst__get_determinize_type(std::s
   __pyx_t_1 = ((!(fst::script::GetDeterminizeType(__pyx_v_det_type, (&__pyx_v_det_type_enum)) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":264
+    /* "pywrapfst.pyx":249
  *   cdef fst.DeterminizeType det_type_enum
  *   if not fst.GetDeterminizeType(det_type, addr(det_type_enum)):
  *     raise FstArgError("Unknown determinization type: {!r}".format(det_type))             # <<<<<<<<<<<<<<
  *   return det_type_enum
  * 
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 264, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 249, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_determinization_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 264, __pyx_L1_error)
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_determinization_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 249, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_det_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 264, __pyx_L1_error)
+    __pyx_t_6 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_det_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 249, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
@@ -4861,41 +4672,11 @@ static enum fst::DeterminizeType __pyx_f_9pywrapfst__get_determinize_type(std::s
         __Pyx_DECREF_SET(__pyx_t_5, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 264, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 264, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 264, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 264, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_6);
-        __pyx_t_6 = 0;
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 264, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 249, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __pyx_t_5 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
@@ -4907,47 +4688,17 @@ static enum fst::DeterminizeType __pyx_f_9pywrapfst__get_determinize_type(std::s
         __Pyx_DECREF_SET(__pyx_t_3, function);
       }
     }
-    if (!__pyx_t_5) {
-      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 264, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_2);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 264, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 264, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 264, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_4);
-        __pyx_t_4 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 264, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 249, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 264, __pyx_L1_error)
+    __PYX_ERR(0, 249, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":263
+    /* "pywrapfst.pyx":248
  *   """
  *   cdef fst.DeterminizeType det_type_enum
  *   if not fst.GetDeterminizeType(det_type, addr(det_type_enum)):             # <<<<<<<<<<<<<<
@@ -4956,7 +4707,7 @@ static enum fst::DeterminizeType __pyx_f_9pywrapfst__get_determinize_type(std::s
  */
   }
 
-  /* "pywrapfst.pyx":265
+  /* "pywrapfst.pyx":250
  *   if not fst.GetDeterminizeType(det_type, addr(det_type_enum)):
  *     raise FstArgError("Unknown determinization type: {!r}".format(det_type))
  *   return det_type_enum             # <<<<<<<<<<<<<<
@@ -4966,7 +4717,7 @@ static enum fst::DeterminizeType __pyx_f_9pywrapfst__get_determinize_type(std::s
   __pyx_r = __pyx_v_det_type_enum;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":247
+  /* "pywrapfst.pyx":232
  * 
  * 
  * cdef fst.DeterminizeType _get_determinize_type(const string &det_type) except *:             # <<<<<<<<<<<<<<
@@ -4982,7 +4733,6 @@ static enum fst::DeterminizeType __pyx_f_9pywrapfst__get_determinize_type(std::s
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._get_determinize_type", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = (enum fst::DeterminizeType) 0;
   __pyx_L0:;
@@ -4990,7 +4740,7 @@ static enum fst::DeterminizeType __pyx_f_9pywrapfst__get_determinize_type(std::s
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":268
+/* "pywrapfst.pyx":253
  * 
  * 
  * cdef fst.QueueType _get_queue_type(const string &queue_type) except *:             # <<<<<<<<<<<<<<
@@ -5009,10 +4759,9 @@ static enum fst::QueueType __pyx_f_9pywrapfst__get_queue_type(std::string const
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_get_queue_type", 0);
 
-  /* "pywrapfst.pyx":287
+  /* "pywrapfst.pyx":272
  *   """
  *   cdef fst.QueueType queue_type_enum
  *   if not fst.GetQueueType(queue_type, addr(queue_type_enum)):             # <<<<<<<<<<<<<<
@@ -5022,18 +4771,18 @@ static enum fst::QueueType __pyx_f_9pywrapfst__get_queue_type(std::string const
   __pyx_t_1 = ((!(fst::script::GetQueueType(__pyx_v_queue_type, (&__pyx_v_queue_type_enum)) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":288
+    /* "pywrapfst.pyx":273
  *   cdef fst.QueueType queue_type_enum
  *   if not fst.GetQueueType(queue_type, addr(queue_type_enum)):
  *     raise FstArgError("Unknown queue type: {!r}".format(queue_type))             # <<<<<<<<<<<<<<
  *   return queue_type_enum
  * 
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 288, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 273, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_queue_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 288, __pyx_L1_error)
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_queue_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 273, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_queue_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 288, __pyx_L1_error)
+    __pyx_t_6 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_queue_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 273, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
@@ -5045,41 +4794,11 @@ static enum fst::QueueType __pyx_f_9pywrapfst__get_queue_type(std::string const
         __Pyx_DECREF_SET(__pyx_t_5, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 288, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 288, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 288, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 288, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_6);
-        __pyx_t_6 = 0;
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 288, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 273, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __pyx_t_5 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
@@ -5091,47 +4810,17 @@ static enum fst::QueueType __pyx_f_9pywrapfst__get_queue_type(std::string const
         __Pyx_DECREF_SET(__pyx_t_3, function);
       }
     }
-    if (!__pyx_t_5) {
-      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 288, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_2);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 288, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 288, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 288, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_4);
-        __pyx_t_4 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 288, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 273, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 288, __pyx_L1_error)
+    __PYX_ERR(0, 273, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":287
+    /* "pywrapfst.pyx":272
  *   """
  *   cdef fst.QueueType queue_type_enum
  *   if not fst.GetQueueType(queue_type, addr(queue_type_enum)):             # <<<<<<<<<<<<<<
@@ -5140,7 +4829,7 @@ static enum fst::QueueType __pyx_f_9pywrapfst__get_queue_type(std::string const
  */
   }
 
-  /* "pywrapfst.pyx":289
+  /* "pywrapfst.pyx":274
  *   if not fst.GetQueueType(queue_type, addr(queue_type_enum)):
  *     raise FstArgError("Unknown queue type: {!r}".format(queue_type))
  *   return queue_type_enum             # <<<<<<<<<<<<<<
@@ -5150,7 +4839,7 @@ static enum fst::QueueType __pyx_f_9pywrapfst__get_queue_type(std::string const
   __pyx_r = __pyx_v_queue_type_enum;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":268
+  /* "pywrapfst.pyx":253
  * 
  * 
  * cdef fst.QueueType _get_queue_type(const string &queue_type) except *:             # <<<<<<<<<<<<<<
@@ -5166,7 +4855,6 @@ static enum fst::QueueType __pyx_f_9pywrapfst__get_queue_type(std::string const
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._get_queue_type", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = (enum fst::QueueType) 0;
   __pyx_L0:;
@@ -5174,7 +4862,7 @@ static enum fst::QueueType __pyx_f_9pywrapfst__get_queue_type(std::string const
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":292
+/* "pywrapfst.pyx":277
  * 
  * 
  * cdef fst.RandArcSelection _get_rand_arc_selection(             # <<<<<<<<<<<<<<
@@ -5193,10 +4881,9 @@ static enum fst::script::RandArcSelection __pyx_f_9pywrapfst__get_rand_arc_selec
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_get_rand_arc_selection", 0);
 
-  /* "pywrapfst.pyx":312
+  /* "pywrapfst.pyx":297
  *   """
  *   cdef fst.RandArcSelection select_enum
  *   if not fst.GetRandArcSelection(select, addr(select_enum)):             # <<<<<<<<<<<<<<
@@ -5206,18 +4893,18 @@ static enum fst::script::RandArcSelection __pyx_f_9pywrapfst__get_rand_arc_selec
   __pyx_t_1 = ((!(fst::script::GetRandArcSelection(__pyx_v_select, (&__pyx_v_select_enum)) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":313
+    /* "pywrapfst.pyx":298
  *   cdef fst.RandArcSelection select_enum
  *   if not fst.GetRandArcSelection(select, addr(select_enum)):
  *     raise FstArgError("Unknown random arc selection type: {!r}".format(select))             # <<<<<<<<<<<<<<
  *   return select_enum
  * 
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 313, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 298, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_random_arc_selection_typ, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 313, __pyx_L1_error)
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_random_arc_selection_typ, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 298, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_select); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 313, __pyx_L1_error)
+    __pyx_t_6 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_select); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 298, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
@@ -5229,41 +4916,11 @@ static enum fst::script::RandArcSelection __pyx_f_9pywrapfst__get_rand_arc_selec
         __Pyx_DECREF_SET(__pyx_t_5, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 313, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 313, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 313, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 313, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_6);
-        __pyx_t_6 = 0;
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 313, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 298, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __pyx_t_5 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
@@ -5275,47 +4932,17 @@ static enum fst::script::RandArcSelection __pyx_f_9pywrapfst__get_rand_arc_selec
         __Pyx_DECREF_SET(__pyx_t_3, function);
       }
     }
-    if (!__pyx_t_5) {
-      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 313, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_2);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 313, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 313, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 313, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_4);
-        __pyx_t_4 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 313, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 298, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 313, __pyx_L1_error)
+    __PYX_ERR(0, 298, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":312
+    /* "pywrapfst.pyx":297
  *   """
  *   cdef fst.RandArcSelection select_enum
  *   if not fst.GetRandArcSelection(select, addr(select_enum)):             # <<<<<<<<<<<<<<
@@ -5324,7 +4951,7 @@ static enum fst::script::RandArcSelection __pyx_f_9pywrapfst__get_rand_arc_selec
  */
   }
 
-  /* "pywrapfst.pyx":314
+  /* "pywrapfst.pyx":299
  *   if not fst.GetRandArcSelection(select, addr(select_enum)):
  *     raise FstArgError("Unknown random arc selection type: {!r}".format(select))
  *   return select_enum             # <<<<<<<<<<<<<<
@@ -5334,7 +4961,7 @@ static enum fst::script::RandArcSelection __pyx_f_9pywrapfst__get_rand_arc_selec
   __pyx_r = __pyx_v_select_enum;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":292
+  /* "pywrapfst.pyx":277
  * 
  * 
  * cdef fst.RandArcSelection _get_rand_arc_selection(             # <<<<<<<<<<<<<<
@@ -5350,7 +4977,6 @@ static enum fst::script::RandArcSelection __pyx_f_9pywrapfst__get_rand_arc_selec
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._get_rand_arc_selection", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = (enum fst::script::RandArcSelection) 0;
   __pyx_L0:;
@@ -5358,7 +4984,7 @@ static enum fst::script::RandArcSelection __pyx_f_9pywrapfst__get_rand_arc_selec
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":317
+/* "pywrapfst.pyx":302
  * 
  * 
  * cdef fst.ReplaceLabelType _get_replace_label_type(             # <<<<<<<<<<<<<<
@@ -5377,10 +5003,9 @@ static enum fst::ReplaceLabelType __pyx_f_9pywrapfst__get_replace_label_type(std
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_get_replace_label_type", 0);
 
-  /* "pywrapfst.pyx":338
+  /* "pywrapfst.pyx":323
  *   """
  *   cdef fst.ReplaceLabelType replace_label_type_enum
  *   if not fst.GetReplaceLabelType(replace_label_type, epsilon_on_replace,             # <<<<<<<<<<<<<<
@@ -5390,26 +5015,26 @@ static enum fst::ReplaceLabelType __pyx_f_9pywrapfst__get_replace_label_type(std
   __pyx_t_1 = ((!(fst::script::GetReplaceLabelType(__pyx_v_replace_label_type, __pyx_v_epsilon_on_replace, (&__pyx_v_replace_label_type_enum)) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":340
+    /* "pywrapfst.pyx":325
  *   if not fst.GetReplaceLabelType(replace_label_type, epsilon_on_replace,
  *                                  addr(replace_label_type_enum)):
  *     raise FstArgError("Unknown replace label type: {!r}".format(             # <<<<<<<<<<<<<<
  *                       replace_label_type))
  *   return replace_label_type_enum
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 340, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 325, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_replace_label_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 340, __pyx_L1_error)
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_replace_label_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 325, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
 
-    /* "pywrapfst.pyx":341
+    /* "pywrapfst.pyx":326
  *                                  addr(replace_label_type_enum)):
  *     raise FstArgError("Unknown replace label type: {!r}".format(
  *                       replace_label_type))             # <<<<<<<<<<<<<<
  *   return replace_label_type_enum
  * 
  */
-    __pyx_t_6 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_replace_label_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 341, __pyx_L1_error)
+    __pyx_t_6 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_replace_label_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 326, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
@@ -5421,41 +5046,11 @@ static enum fst::ReplaceLabelType __pyx_f_9pywrapfst__get_replace_label_type(std
         __Pyx_DECREF_SET(__pyx_t_5, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 340, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 340, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 340, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 340, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_6);
-        __pyx_t_6 = 0;
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 340, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 325, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __pyx_t_5 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
@@ -5467,47 +5062,17 @@ static enum fst::ReplaceLabelType __pyx_f_9pywrapfst__get_replace_label_type(std
         __Pyx_DECREF_SET(__pyx_t_3, function);
       }
     }
-    if (!__pyx_t_5) {
-      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 340, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_2);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 340, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 340, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 340, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_4);
-        __pyx_t_4 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 340, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 325, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 340, __pyx_L1_error)
+    __PYX_ERR(0, 325, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":338
+    /* "pywrapfst.pyx":323
  *   """
  *   cdef fst.ReplaceLabelType replace_label_type_enum
  *   if not fst.GetReplaceLabelType(replace_label_type, epsilon_on_replace,             # <<<<<<<<<<<<<<
@@ -5516,7 +5081,7 @@ static enum fst::ReplaceLabelType __pyx_f_9pywrapfst__get_replace_label_type(std
  */
   }
 
-  /* "pywrapfst.pyx":342
+  /* "pywrapfst.pyx":327
  *     raise FstArgError("Unknown replace label type: {!r}".format(
  *                       replace_label_type))
  *   return replace_label_type_enum             # <<<<<<<<<<<<<<
@@ -5526,7 +5091,7 @@ static enum fst::ReplaceLabelType __pyx_f_9pywrapfst__get_replace_label_type(std
   __pyx_r = __pyx_v_replace_label_type_enum;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":317
+  /* "pywrapfst.pyx":302
  * 
  * 
  * cdef fst.ReplaceLabelType _get_replace_label_type(             # <<<<<<<<<<<<<<
@@ -5542,7 +5107,6 @@ static enum fst::ReplaceLabelType __pyx_f_9pywrapfst__get_replace_label_type(std
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._get_replace_label_type", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = (enum fst::ReplaceLabelType) 0;
   __pyx_L0:;
@@ -5550,7 +5114,7 @@ static enum fst::ReplaceLabelType __pyx_f_9pywrapfst__get_replace_label_type(std
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":368
+/* "pywrapfst.pyx":353
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -5584,7 +5148,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight___repr__(struct __pyx_obj_9pywrapfs
   PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":369
+  /* "pywrapfst.pyx":354
  * 
  *   def __repr__(self):
  *     return "<{} Weight {} at 0x{:x}>".format(self.type(), self.to_string(),             # <<<<<<<<<<<<<<
@@ -5592,29 +5156,29 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight___repr__(struct __pyx_obj_9pywrapfs
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Weight_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 369, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Weight_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 354, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "type");
-    __PYX_ERR(0, 369, __pyx_L1_error)
+    __PYX_ERR(0, 354, __pyx_L1_error)
   }
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->type(__pyx_v_self, 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 369, __pyx_L1_error)
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->type(__pyx_v_self, 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 354, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "to_string");
-    __PYX_ERR(0, 369, __pyx_L1_error)
+    __PYX_ERR(0, 354, __pyx_L1_error)
   }
-  __pyx_t_4 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->to_string(__pyx_v_self, 0)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 369, __pyx_L1_error)
+  __pyx_t_4 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->to_string(__pyx_v_self, 0)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 354, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
 
-  /* "pywrapfst.pyx":370
+  /* "pywrapfst.pyx":355
  *   def __repr__(self):
  *     return "<{} Weight {} at 0x{:x}>".format(self.type(), self.to_string(),
  *                                              id(self))             # <<<<<<<<<<<<<<
  * 
  *   def __str__(self):
  */
-  __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 370, __pyx_L1_error)
+  __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 355, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_5);
   __pyx_t_6 = NULL;
   __pyx_t_7 = 0;
@@ -5631,7 +5195,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight___repr__(struct __pyx_obj_9pywrapfs
   #if CYTHON_FAST_PYCALL
   if (PyFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[4] = {__pyx_t_6, __pyx_t_3, __pyx_t_4, __pyx_t_5};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 369, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 354, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -5642,7 +5206,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight___repr__(struct __pyx_obj_9pywrapfs
   #if CYTHON_FAST_PYCCALL
   if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[4] = {__pyx_t_6, __pyx_t_3, __pyx_t_4, __pyx_t_5};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 369, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_7, 3+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 354, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -5651,7 +5215,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight___repr__(struct __pyx_obj_9pywrapfs
   } else
   #endif
   {
-    __pyx_t_8 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 369, __pyx_L1_error)
+    __pyx_t_8 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 354, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_8);
     if (__pyx_t_6) {
       __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
@@ -5665,7 +5229,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight___repr__(struct __pyx_obj_9pywrapfs
     __pyx_t_3 = 0;
     __pyx_t_4 = 0;
     __pyx_t_5 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 369, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 354, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
   }
@@ -5674,7 +5238,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight___repr__(struct __pyx_obj_9pywrapfs
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":368
+  /* "pywrapfst.pyx":353
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -5699,7 +5263,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight___repr__(struct __pyx_obj_9pywrapfs
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":372
+/* "pywrapfst.pyx":357
  *                                              id(self))
  * 
  *   def __str__(self):             # <<<<<<<<<<<<<<
@@ -5726,7 +5290,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_2__str__(struct __pyx_obj_9pywrapfs
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__str__", 0);
 
-  /* "pywrapfst.pyx":373
+  /* "pywrapfst.pyx":358
  * 
  *   def __str__(self):
  *     return self.to_string()             # <<<<<<<<<<<<<<
@@ -5736,15 +5300,15 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_2__str__(struct __pyx_obj_9pywrapfs
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "to_string");
-    __PYX_ERR(0, 373, __pyx_L1_error)
+    __PYX_ERR(0, 358, __pyx_L1_error)
   }
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->to_string(__pyx_v_self, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 373, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->to_string(__pyx_v_self, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 358, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":372
+  /* "pywrapfst.pyx":357
  *                                              id(self))
  * 
  *   def __str__(self):             # <<<<<<<<<<<<<<
@@ -5763,7 +5327,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_2__str__(struct __pyx_obj_9pywrapfs
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":378
+/* "pywrapfst.pyx":363
  *   # ValueError when that is not appropriate.
  * 
  *   def __float__(self):             # <<<<<<<<<<<<<<
@@ -5791,7 +5355,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_4__float__(struct __pyx_obj_9pywrap
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("__float__", 0);
 
-  /* "pywrapfst.pyx":379
+  /* "pywrapfst.pyx":364
  * 
  *   def __float__(self):
  *     return float(self.to_string())             # <<<<<<<<<<<<<<
@@ -5801,18 +5365,18 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_4__float__(struct __pyx_obj_9pywrap
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "to_string");
-    __PYX_ERR(0, 379, __pyx_L1_error)
+    __PYX_ERR(0, 364, __pyx_L1_error)
   }
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->to_string(__pyx_v_self, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 379, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->to_string(__pyx_v_self, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 364, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyNumber_Float(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 379, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyNumber_Float(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 364, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":378
+  /* "pywrapfst.pyx":363
  *   # ValueError when that is not appropriate.
  * 
  *   def __float__(self):             # <<<<<<<<<<<<<<
@@ -5832,7 +5396,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_4__float__(struct __pyx_obj_9pywrap
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":381
+/* "pywrapfst.pyx":366
  *     return float(self.to_string())
  * 
  *   def __init__(self, weight_type, weight):             # <<<<<<<<<<<<<<
@@ -5871,11 +5435,11 @@ static int __pyx_pw_9pywrapfst_6Weight_7__init__(PyObject *__pyx_v_self, PyObjec
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_weight)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 381, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 366, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 381, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 366, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -5888,7 +5452,7 @@ static int __pyx_pw_9pywrapfst_6Weight_7__init__(PyObject *__pyx_v_self, PyObjec
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 381, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 366, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.Weight.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -5908,7 +5472,7 @@ static int __pyx_pf_9pywrapfst_6Weight_6__init__(struct __pyx_obj_9pywrapfst_Wei
   std::string __pyx_t_2;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":382
+  /* "pywrapfst.pyx":367
  * 
  *   def __init__(self, weight_type, weight):
  *     self._weight.reset(new fst.WeightClass(tostring(weight_type),             # <<<<<<<<<<<<<<
@@ -5917,20 +5481,20 @@ static int __pyx_pf_9pywrapfst_6Weight_6__init__(struct __pyx_obj_9pywrapfst_Wei
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 382, __pyx_L1_error)
+    __PYX_ERR(0, 367, __pyx_L1_error)
   }
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_weight_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 382, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_weight_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 367, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":383
+  /* "pywrapfst.pyx":368
  *   def __init__(self, weight_type, weight):
  *     self._weight.reset(new fst.WeightClass(tostring(weight_type),
  *                                            weight_tostring(weight)))             # <<<<<<<<<<<<<<
  *     self._check_weight()
  * 
  */
-  __pyx_t_2 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 383, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 368, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":382
+  /* "pywrapfst.pyx":367
  * 
  *   def __init__(self, weight_type, weight):
  *     self._weight.reset(new fst.WeightClass(tostring(weight_type),             # <<<<<<<<<<<<<<
@@ -5939,7 +5503,7 @@ static int __pyx_pf_9pywrapfst_6Weight_6__init__(struct __pyx_obj_9pywrapfst_Wei
  */
   __pyx_v_self->_weight.reset(new fst::script::WeightClass(__pyx_t_1, __pyx_t_2));
 
-  /* "pywrapfst.pyx":384
+  /* "pywrapfst.pyx":369
  *     self._weight.reset(new fst.WeightClass(tostring(weight_type),
  *                                            weight_tostring(weight)))
  *     self._check_weight()             # <<<<<<<<<<<<<<
@@ -5948,11 +5512,11 @@ static int __pyx_pf_9pywrapfst_6Weight_6__init__(struct __pyx_obj_9pywrapfst_Wei
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_weight");
-    __PYX_ERR(0, 384, __pyx_L1_error)
+    __PYX_ERR(0, 369, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->_check_weight(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 384, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->_check_weight(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 369, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":381
+  /* "pywrapfst.pyx":366
  *     return float(self.to_string())
  * 
  *   def __init__(self, weight_type, weight):             # <<<<<<<<<<<<<<
@@ -5971,7 +5535,7 @@ static int __pyx_pf_9pywrapfst_6Weight_6__init__(struct __pyx_obj_9pywrapfst_Wei
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":386
+/* "pywrapfst.pyx":371
  *     self._check_weight()
  * 
  *   cdef void _check_weight(self) except *:             # <<<<<<<<<<<<<<
@@ -5984,9 +5548,10 @@ static void __pyx_f_9pywrapfst_6Weight__check_weight(struct __pyx_obj_9pywrapfst
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("_check_weight", 0);
 
-  /* "pywrapfst.pyx":387
+  /* "pywrapfst.pyx":372
  * 
  *   cdef void _check_weight(self) except *:
  *     if self.type() == b"none":             # <<<<<<<<<<<<<<
@@ -5995,28 +5560,40 @@ static void __pyx_f_9pywrapfst_6Weight__check_weight(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "type");
-    __PYX_ERR(0, 387, __pyx_L1_error)
+    __PYX_ERR(0, 372, __pyx_L1_error)
   }
   __pyx_t_1 = ((((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->type(__pyx_v_self, 0) == ((char const *)"none")) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":388
+    /* "pywrapfst.pyx":373
  *   cdef void _check_weight(self) except *:
  *     if self.type() == b"none":
  *       raise FstArgError("Weight type not found")             # <<<<<<<<<<<<<<
  *     if self.to_string() == b"BadNumber":
  *       raise FstBadWeightError("Invalid weight")
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 388, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 388, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 373, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_Weight_type_not_found) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_Weight_type_not_found);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 373, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 388, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 373, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":387
+    /* "pywrapfst.pyx":372
  * 
  *   cdef void _check_weight(self) except *:
  *     if self.type() == b"none":             # <<<<<<<<<<<<<<
@@ -6025,7 +5602,7 @@ static void __pyx_f_9pywrapfst_6Weight__check_weight(struct __pyx_obj_9pywrapfst
  */
   }
 
-  /* "pywrapfst.pyx":389
+  /* "pywrapfst.pyx":374
  *     if self.type() == b"none":
  *       raise FstArgError("Weight type not found")
  *     if self.to_string() == b"BadNumber":             # <<<<<<<<<<<<<<
@@ -6034,28 +5611,40 @@ static void __pyx_f_9pywrapfst_6Weight__check_weight(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "to_string");
-    __PYX_ERR(0, 389, __pyx_L1_error)
+    __PYX_ERR(0, 374, __pyx_L1_error)
   }
   __pyx_t_1 = ((((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_self->__pyx_vtab)->to_string(__pyx_v_self, 0) == ((char const *)"BadNumber")) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":390
+    /* "pywrapfst.pyx":375
  *       raise FstArgError("Weight type not found")
  *     if self.to_string() == b"BadNumber":
  *       raise FstBadWeightError("Invalid weight")             # <<<<<<<<<<<<<<
  * 
  *   cpdef Weight copy(self):
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstBadWeightError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 390, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstBadWeightError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 375, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 390, __pyx_L1_error)
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_Invalid_weight) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_Invalid_weight);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 375, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 390, __pyx_L1_error)
+    __PYX_ERR(0, 375, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":389
+    /* "pywrapfst.pyx":374
  *     if self.type() == b"none":
  *       raise FstArgError("Weight type not found")
  *     if self.to_string() == b"BadNumber":             # <<<<<<<<<<<<<<
@@ -6064,7 +5653,7 @@ static void __pyx_f_9pywrapfst_6Weight__check_weight(struct __pyx_obj_9pywrapfst
  */
   }
 
-  /* "pywrapfst.pyx":386
+  /* "pywrapfst.pyx":371
  *     self._check_weight()
  * 
  *   cdef void _check_weight(self) except *:             # <<<<<<<<<<<<<<
@@ -6077,12 +5666,13 @@ static void __pyx_f_9pywrapfst_6Weight__check_weight(struct __pyx_obj_9pywrapfst
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst.Weight._check_weight", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":392
+/* "pywrapfst.pyx":377
  *       raise FstBadWeightError("Invalid weight")
  * 
  *   cpdef Weight copy(self):             # <<<<<<<<<<<<<<
@@ -6103,52 +5693,65 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst_6Weight_copy(struc
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_copy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 392, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_6Weight_9copy)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_copy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 377, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_6Weight_9copy)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 377, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_Weight))))) __PYX_ERR(0, 377, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 392, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 392, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_Weight))))) __PYX_ERR(0, 392, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":398
+  /* "pywrapfst.pyx":383
  *     Returns a copy of the Weight.
  *     """
  *     cdef Weight result = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *     result._weight.reset(new fst.WeightClass(deref(self._weight)))
  *     return result
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 398, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 383, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":399
+  /* "pywrapfst.pyx":384
  *     """
  *     cdef Weight result = Weight.__new__(Weight)
  *     result._weight.reset(new fst.WeightClass(deref(self._weight)))             # <<<<<<<<<<<<<<
@@ -6157,15 +5760,15 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst_6Weight_copy(struc
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 399, __pyx_L1_error)
+    __PYX_ERR(0, 384, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 399, __pyx_L1_error)
+    __PYX_ERR(0, 384, __pyx_L1_error)
   }
   __pyx_v_result->_weight.reset(new fst::script::WeightClass((*__pyx_v_self->_weight)));
 
-  /* "pywrapfst.pyx":400
+  /* "pywrapfst.pyx":385
  *     cdef Weight result = Weight.__new__(Weight)
  *     result._weight.reset(new fst.WeightClass(deref(self._weight)))
  *     return result             # <<<<<<<<<<<<<<
@@ -6177,7 +5780,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst_6Weight_copy(struc
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":392
+  /* "pywrapfst.pyx":377
  *       raise FstBadWeightError("Invalid weight")
  * 
  *   cpdef Weight copy(self):             # <<<<<<<<<<<<<<
@@ -6220,7 +5823,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_8copy(struct __pyx_obj_9pywrapfst_W
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("copy", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_6Weight_copy(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 392, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_6Weight_copy(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 377, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -6237,7 +5840,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_8copy(struct __pyx_obj_9pywrapfst_W
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":406
+/* "pywrapfst.pyx":391
  * 
  *   @classmethod
  *   def Zero(cls, weight_type):             # <<<<<<<<<<<<<<
@@ -6265,7 +5868,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_10Zero(CYTHON_UNUSED PyTypeObject *
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("Zero", 0);
 
-  /* "pywrapfst.pyx":412
+  /* "pywrapfst.pyx":397
  *     Constructs semiring zero.
  *     """
  *     return _Zero(weight_type)             # <<<<<<<<<<<<<<
@@ -6273,13 +5876,13 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_10Zero(CYTHON_UNUSED PyTypeObject *
  *   @classmethod
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__Zero(__pyx_v_weight_type)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 412, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__Zero(__pyx_v_weight_type)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 397, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":406
+  /* "pywrapfst.pyx":391
  * 
  *   @classmethod
  *   def Zero(cls, weight_type):             # <<<<<<<<<<<<<<
@@ -6298,7 +5901,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_10Zero(CYTHON_UNUSED PyTypeObject *
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":415
+/* "pywrapfst.pyx":400
  * 
  *   @classmethod
  *   def One(cls, weight_type):             # <<<<<<<<<<<<<<
@@ -6326,7 +5929,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_12One(CYTHON_UNUSED PyTypeObject *_
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("One", 0);
 
-  /* "pywrapfst.pyx":421
+  /* "pywrapfst.pyx":406
  *     Constructs semiring One.
  *     """
  *     return _One(weight_type)             # <<<<<<<<<<<<<<
@@ -6334,13 +5937,13 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_12One(CYTHON_UNUSED PyTypeObject *_
  *   @classmethod
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__One(__pyx_v_weight_type)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 421, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__One(__pyx_v_weight_type)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 406, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":415
+  /* "pywrapfst.pyx":400
  * 
  *   @classmethod
  *   def One(cls, weight_type):             # <<<<<<<<<<<<<<
@@ -6359,7 +5962,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_12One(CYTHON_UNUSED PyTypeObject *_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":424
+/* "pywrapfst.pyx":409
  * 
  *   @classmethod
  *   def NoWeight(cls, weight_type):             # <<<<<<<<<<<<<<
@@ -6387,7 +5990,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_14NoWeight(CYTHON_UNUSED PyTypeObje
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("NoWeight", 0);
 
-  /* "pywrapfst.pyx":430
+  /* "pywrapfst.pyx":415
  *     Constructs a non-member weight in the semiring.
  *     """
  *     return _NoWeight(weight_type)             # <<<<<<<<<<<<<<
@@ -6395,13 +5998,13 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_14NoWeight(CYTHON_UNUSED PyTypeObje
  *   def __eq__(Weight w1, Weight w2):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__NoWeight(__pyx_v_weight_type)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 430, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__NoWeight(__pyx_v_weight_type)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 415, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":424
+  /* "pywrapfst.pyx":409
  * 
  *   @classmethod
  *   def NoWeight(cls, weight_type):             # <<<<<<<<<<<<<<
@@ -6420,7 +6023,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_14NoWeight(CYTHON_UNUSED PyTypeObje
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":432
+/* "pywrapfst.pyx":417
  *     return _NoWeight(weight_type)
  * 
  *   def __eq__(Weight w1, Weight w2):             # <<<<<<<<<<<<<<
@@ -6434,7 +6037,7 @@ static PyObject *__pyx_pw_9pywrapfst_6Weight_17__eq__(PyObject *__pyx_v_w1, PyOb
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__eq__ (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w2), __pyx_ptype_9pywrapfst_Weight, 1, "w2", 0))) __PYX_ERR(0, 432, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w2), __pyx_ptype_9pywrapfst_Weight, 1, "w2", 0))) __PYX_ERR(0, 417, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_6Weight_16__eq__(((struct __pyx_obj_9pywrapfst_Weight *)__pyx_v_w1), ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_v_w2));
 
   /* function exit code */
@@ -6452,7 +6055,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_16__eq__(struct __pyx_obj_9pywrapfs
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__eq__", 0);
 
-  /* "pywrapfst.pyx":433
+  /* "pywrapfst.pyx":418
  * 
  *   def __eq__(Weight w1, Weight w2):
  *     return fst.Eq(deref(w1._weight), deref(w2._weight))             # <<<<<<<<<<<<<<
@@ -6462,19 +6065,19 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_16__eq__(struct __pyx_obj_9pywrapfs
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_w1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 433, __pyx_L1_error)
+    __PYX_ERR(0, 418, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_w2) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 433, __pyx_L1_error)
+    __PYX_ERR(0, 418, __pyx_L1_error)
   }
-  __pyx_t_1 = __Pyx_PyBool_FromLong(operator==((*__pyx_v_w1->_weight), (*__pyx_v_w2->_weight))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 433, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(operator==((*__pyx_v_w1->_weight), (*__pyx_v_w2->_weight))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 418, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":432
+  /* "pywrapfst.pyx":417
  *     return _NoWeight(weight_type)
  * 
  *   def __eq__(Weight w1, Weight w2):             # <<<<<<<<<<<<<<
@@ -6493,7 +6096,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_16__eq__(struct __pyx_obj_9pywrapfs
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":435
+/* "pywrapfst.pyx":420
  *     return fst.Eq(deref(w1._weight), deref(w2._weight))
  * 
  *   def __ne__(Weight w1, Weight w2):             # <<<<<<<<<<<<<<
@@ -6507,7 +6110,7 @@ static PyObject *__pyx_pw_9pywrapfst_6Weight_19__ne__(PyObject *__pyx_v_w1, PyOb
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__ne__ (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w2), __pyx_ptype_9pywrapfst_Weight, 1, "w2", 0))) __PYX_ERR(0, 435, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w2), __pyx_ptype_9pywrapfst_Weight, 1, "w2", 0))) __PYX_ERR(0, 420, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_6Weight_18__ne__(((struct __pyx_obj_9pywrapfst_Weight *)__pyx_v_w1), ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_v_w2));
 
   /* function exit code */
@@ -6526,7 +6129,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_18__ne__(struct __pyx_obj_9pywrapfs
   int __pyx_t_2;
   __Pyx_RefNannySetupContext("__ne__", 0);
 
-  /* "pywrapfst.pyx":436
+  /* "pywrapfst.pyx":421
  * 
  *   def __ne__(Weight w1, Weight w2):
  *     return not w1 == w2             # <<<<<<<<<<<<<<
@@ -6534,16 +6137,16 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_18__ne__(struct __pyx_obj_9pywrapfs
  *   cpdef string to_string(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyObject_RichCompare(((PyObject *)__pyx_v_w1), ((PyObject *)__pyx_v_w2), Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 436, __pyx_L1_error)
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 436, __pyx_L1_error)
+  __pyx_t_1 = PyObject_RichCompare(((PyObject *)__pyx_v_w1), ((PyObject *)__pyx_v_w2), Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 421, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 421, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyBool_FromLong((!__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 436, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong((!__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 421, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":435
+  /* "pywrapfst.pyx":420
  *     return fst.Eq(deref(w1._weight), deref(w2._weight))
  * 
  *   def __ne__(Weight w1, Weight w2):             # <<<<<<<<<<<<<<
@@ -6562,7 +6165,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_18__ne__(struct __pyx_obj_9pywrapfs
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":438
+/* "pywrapfst.pyx":423
  *     return not w1 == w2
  * 
  *   cpdef string to_string(self):             # <<<<<<<<<<<<<<
@@ -6583,39 +6186,52 @@ static std::string __pyx_f_9pywrapfst_6Weight_to_string(struct __pyx_obj_9pywrap
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_to_string); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 438, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_6Weight_21to_string)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_to_string); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 423, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_6Weight_21to_string)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 423, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 423, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 438, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 438, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 438, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":439
+  /* "pywrapfst.pyx":424
  * 
  *   cpdef string to_string(self):
  *     return self._weight.get().ToString()             # <<<<<<<<<<<<<<
@@ -6624,12 +6240,12 @@ static std::string __pyx_f_9pywrapfst_6Weight_to_string(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 439, __pyx_L1_error)
+    __PYX_ERR(0, 424, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_weight.get()->ToString();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":438
+  /* "pywrapfst.pyx":423
  *     return not w1 == w2
  * 
  *   cpdef string to_string(self):             # <<<<<<<<<<<<<<
@@ -6669,7 +6285,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_20to_string(struct __pyx_obj_9pywra
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("to_string", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_6Weight_to_string(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 438, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_6Weight_to_string(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 423, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -6686,7 +6302,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_20to_string(struct __pyx_obj_9pywra
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":441
+/* "pywrapfst.pyx":426
  *     return self._weight.get().ToString()
  * 
  *   cpdef string type(self):             # <<<<<<<<<<<<<<
@@ -6707,39 +6323,52 @@ static std::string __pyx_f_9pywrapfst_6Weight_type(struct __pyx_obj_9pywrapfst_W
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 441, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_6Weight_23type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 426, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_6Weight_23type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 426, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 426, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 441, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 441, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 441, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":446
+  /* "pywrapfst.pyx":431
  *     Returns a string indicating the weight type.
  *     """
  *     return self._weight.get().Type()             # <<<<<<<<<<<<<<
@@ -6748,12 +6377,12 @@ static std::string __pyx_f_9pywrapfst_6Weight_type(struct __pyx_obj_9pywrapfst_W
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 446, __pyx_L1_error)
+    __PYX_ERR(0, 431, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_weight.get()->Type();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":441
+  /* "pywrapfst.pyx":426
  *     return self._weight.get().ToString()
  * 
  *   cpdef string type(self):             # <<<<<<<<<<<<<<
@@ -6794,7 +6423,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_22type(struct __pyx_obj_9pywrapfst_
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_6Weight_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 441, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_6Weight_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 426, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -6842,7 +6471,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_24__reduce_cython__(CYTHON_UNUSED s
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._weight cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -6895,7 +6524,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_26__setstate_cython__(CYTHON_UNUSED
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._weight cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -6918,7 +6547,7 @@ static PyObject *__pyx_pf_9pywrapfst_6Weight_26__setstate_cython__(CYTHON_UNUSED
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":449
+/* "pywrapfst.pyx":434
  * 
  * 
  * cdef Weight _plus(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -6933,19 +6562,19 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__plus(struct __pyx
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("_plus", 0);
 
-  /* "pywrapfst.pyx":450
+  /* "pywrapfst.pyx":435
  * 
  * cdef Weight _plus(Weight lhs, Weight rhs):
  *   cdef Weight result = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *   result._weight.reset(new fst.WeightClass(fst.Plus(deref(lhs._weight),
  *                                                     deref(rhs._weight))))
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 450, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 435, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":451
+  /* "pywrapfst.pyx":436
  * cdef Weight _plus(Weight lhs, Weight rhs):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Plus(deref(lhs._weight),             # <<<<<<<<<<<<<<
@@ -6954,14 +6583,14 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__plus(struct __pyx
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 451, __pyx_L1_error)
+    __PYX_ERR(0, 436, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_lhs) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 451, __pyx_L1_error)
+    __PYX_ERR(0, 436, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":452
+  /* "pywrapfst.pyx":437
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Plus(deref(lhs._weight),
  *                                                     deref(rhs._weight))))             # <<<<<<<<<<<<<<
@@ -6970,10 +6599,10 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__plus(struct __pyx
  */
   if (unlikely(((PyObject *)__pyx_v_rhs) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 452, __pyx_L1_error)
+    __PYX_ERR(0, 437, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":451
+  /* "pywrapfst.pyx":436
  * cdef Weight _plus(Weight lhs, Weight rhs):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Plus(deref(lhs._weight),             # <<<<<<<<<<<<<<
@@ -6982,7 +6611,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__plus(struct __pyx
  */
   __pyx_v_result->_weight.reset(new fst::script::WeightClass(fst::script::Plus((*__pyx_v_lhs->_weight), (*__pyx_v_rhs->_weight))));
 
-  /* "pywrapfst.pyx":453
+  /* "pywrapfst.pyx":438
  *   result._weight.reset(new fst.WeightClass(fst.Plus(deref(lhs._weight),
  *                                                     deref(rhs._weight))))
  *   return result             # <<<<<<<<<<<<<<
@@ -6994,7 +6623,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__plus(struct __pyx
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":449
+  /* "pywrapfst.pyx":434
  * 
  * 
  * cdef Weight _plus(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7014,7 +6643,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__plus(struct __pyx
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":456
+/* "pywrapfst.pyx":441
  * 
  * 
  * def plus(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7025,7 +6654,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__plus(struct __pyx
 /* Python wrapper */
 static PyObject *__pyx_pw_9pywrapfst_1plus(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static char __pyx_doc_9pywrapfst_plus[] = "\n  plus(lhs, rhs)\n\n  Computes the sum of two Weights in the same semiring.\n\n  This function computes lhs \\oplus rhs, raising an exception if lhs and rhs\n  are not in the same semiring.\n\n  Args:\n     lhs: Left-hand side Weight.\n     rhs: Right-hand side Weight.\n\n  Returns:\n    A Weight object.\n\n  Raises:\n    FstArgError: Weight type not found (or not in same semiring).\n    FstBadWeightError: invalid weight.\n  ";
-static PyMethodDef __pyx_mdef_9pywrapfst_1plus = {"plus", (PyCFunction)__pyx_pw_9pywrapfst_1plus, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_plus};
+static PyMethodDef __pyx_mdef_9pywrapfst_1plus = {"plus", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_1plus, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_plus};
 static PyObject *__pyx_pw_9pywrapfst_1plus(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst_Weight *__pyx_v_lhs = 0;
   struct __pyx_obj_9pywrapfst_Weight *__pyx_v_rhs = 0;
@@ -7055,11 +6684,11 @@ static PyObject *__pyx_pw_9pywrapfst_1plus(PyObject *__pyx_self, PyObject *__pyx
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rhs)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("plus", 1, 2, 2, 1); __PYX_ERR(0, 456, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("plus", 1, 2, 2, 1); __PYX_ERR(0, 441, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "plus") < 0)) __PYX_ERR(0, 456, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "plus") < 0)) __PYX_ERR(0, 441, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -7072,14 +6701,14 @@ static PyObject *__pyx_pw_9pywrapfst_1plus(PyObject *__pyx_self, PyObject *__pyx
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("plus", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 456, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("plus", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 441, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.plus", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lhs), __pyx_ptype_9pywrapfst_Weight, 1, "lhs", 0))) __PYX_ERR(0, 456, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_rhs), __pyx_ptype_9pywrapfst_Weight, 1, "rhs", 0))) __PYX_ERR(0, 456, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lhs), __pyx_ptype_9pywrapfst_Weight, 1, "lhs", 0))) __PYX_ERR(0, 441, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_rhs), __pyx_ptype_9pywrapfst_Weight, 1, "rhs", 0))) __PYX_ERR(0, 441, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_plus(__pyx_self, __pyx_v_lhs, __pyx_v_rhs);
 
   /* function exit code */
@@ -7098,19 +6727,19 @@ static PyObject *__pyx_pf_9pywrapfst_plus(CYTHON_UNUSED PyObject *__pyx_self, st
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("plus", 0);
 
-  /* "pywrapfst.pyx":476
+  /* "pywrapfst.pyx":461
  *     FstBadWeightError: invalid weight.
  *   """
  *   cdef Weight result = _plus(lhs, rhs)             # <<<<<<<<<<<<<<
  *   result._check_weight()
  *   return result
  */
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__plus(__pyx_v_lhs, __pyx_v_rhs)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 476, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__plus(__pyx_v_lhs, __pyx_v_rhs)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 461, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":477
+  /* "pywrapfst.pyx":462
  *   """
  *   cdef Weight result = _plus(lhs, rhs)
  *   result._check_weight()             # <<<<<<<<<<<<<<
@@ -7119,11 +6748,11 @@ static PyObject *__pyx_pf_9pywrapfst_plus(CYTHON_UNUSED PyObject *__pyx_self, st
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_weight");
-    __PYX_ERR(0, 477, __pyx_L1_error)
+    __PYX_ERR(0, 462, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_result->__pyx_vtab)->_check_weight(__pyx_v_result); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 477, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_result->__pyx_vtab)->_check_weight(__pyx_v_result); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 462, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":478
+  /* "pywrapfst.pyx":463
  *   cdef Weight result = _plus(lhs, rhs)
  *   result._check_weight()
  *   return result             # <<<<<<<<<<<<<<
@@ -7135,7 +6764,7 @@ static PyObject *__pyx_pf_9pywrapfst_plus(CYTHON_UNUSED PyObject *__pyx_self, st
   __pyx_r = ((PyObject *)__pyx_v_result);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":456
+  /* "pywrapfst.pyx":441
  * 
  * 
  * def plus(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7155,7 +6784,7 @@ static PyObject *__pyx_pf_9pywrapfst_plus(CYTHON_UNUSED PyObject *__pyx_self, st
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":481
+/* "pywrapfst.pyx":466
  * 
  * 
  * cdef Weight _times(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7170,19 +6799,19 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__times(struct __py
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("_times", 0);
 
-  /* "pywrapfst.pyx":482
+  /* "pywrapfst.pyx":467
  * 
  * cdef Weight _times(Weight lhs, Weight rhs):
  *   cdef Weight result = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *   result._weight.reset(new fst.WeightClass(fst.Times(deref(lhs._weight),
  *                                                      deref(rhs._weight))))
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 482, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 467, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":483
+  /* "pywrapfst.pyx":468
  * cdef Weight _times(Weight lhs, Weight rhs):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Times(deref(lhs._weight),             # <<<<<<<<<<<<<<
@@ -7191,14 +6820,14 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__times(struct __py
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 483, __pyx_L1_error)
+    __PYX_ERR(0, 468, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_lhs) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 483, __pyx_L1_error)
+    __PYX_ERR(0, 468, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":484
+  /* "pywrapfst.pyx":469
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Times(deref(lhs._weight),
  *                                                      deref(rhs._weight))))             # <<<<<<<<<<<<<<
@@ -7207,10 +6836,10 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__times(struct __py
  */
   if (unlikely(((PyObject *)__pyx_v_rhs) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 484, __pyx_L1_error)
+    __PYX_ERR(0, 469, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":483
+  /* "pywrapfst.pyx":468
  * cdef Weight _times(Weight lhs, Weight rhs):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Times(deref(lhs._weight),             # <<<<<<<<<<<<<<
@@ -7219,7 +6848,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__times(struct __py
  */
   __pyx_v_result->_weight.reset(new fst::script::WeightClass(fst::script::Times((*__pyx_v_lhs->_weight), (*__pyx_v_rhs->_weight))));
 
-  /* "pywrapfst.pyx":485
+  /* "pywrapfst.pyx":470
  *   result._weight.reset(new fst.WeightClass(fst.Times(deref(lhs._weight),
  *                                                      deref(rhs._weight))))
  *   return result             # <<<<<<<<<<<<<<
@@ -7231,7 +6860,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__times(struct __py
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":481
+  /* "pywrapfst.pyx":466
  * 
  * 
  * cdef Weight _times(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7251,7 +6880,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__times(struct __py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":488
+/* "pywrapfst.pyx":473
  * 
  * 
  * def times(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7262,7 +6891,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__times(struct __py
 /* Python wrapper */
 static PyObject *__pyx_pw_9pywrapfst_3times(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static char __pyx_doc_9pywrapfst_2times[] = "\n  times(lhs, rhs)\n\n  Computes the product of two Weights in the same semiring.\n\n  This function computes lhs \\otimes rhs, raising an exception if lhs and rhs\n  are not in the same semiring.\n\n  Args:\n     lhs: Left-hand side Weight.\n     rhs: Right-hand side Weight.\n\n  Returns:\n    A Weight object.\n\n  Raises:\n    FstArgError: Weight type not found (or not in same semiring).\n    FstBadWeightError: Invalid weight.\n  ";
-static PyMethodDef __pyx_mdef_9pywrapfst_3times = {"times", (PyCFunction)__pyx_pw_9pywrapfst_3times, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_2times};
+static PyMethodDef __pyx_mdef_9pywrapfst_3times = {"times", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_3times, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_2times};
 static PyObject *__pyx_pw_9pywrapfst_3times(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst_Weight *__pyx_v_lhs = 0;
   struct __pyx_obj_9pywrapfst_Weight *__pyx_v_rhs = 0;
@@ -7292,11 +6921,11 @@ static PyObject *__pyx_pw_9pywrapfst_3times(PyObject *__pyx_self, PyObject *__py
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rhs)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("times", 1, 2, 2, 1); __PYX_ERR(0, 488, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("times", 1, 2, 2, 1); __PYX_ERR(0, 473, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "times") < 0)) __PYX_ERR(0, 488, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "times") < 0)) __PYX_ERR(0, 473, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -7309,14 +6938,14 @@ static PyObject *__pyx_pw_9pywrapfst_3times(PyObject *__pyx_self, PyObject *__py
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("times", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 488, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("times", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 473, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.times", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lhs), __pyx_ptype_9pywrapfst_Weight, 1, "lhs", 0))) __PYX_ERR(0, 488, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_rhs), __pyx_ptype_9pywrapfst_Weight, 1, "rhs", 0))) __PYX_ERR(0, 488, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lhs), __pyx_ptype_9pywrapfst_Weight, 1, "lhs", 0))) __PYX_ERR(0, 473, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_rhs), __pyx_ptype_9pywrapfst_Weight, 1, "rhs", 0))) __PYX_ERR(0, 473, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_2times(__pyx_self, __pyx_v_lhs, __pyx_v_rhs);
 
   /* function exit code */
@@ -7335,19 +6964,19 @@ static PyObject *__pyx_pf_9pywrapfst_2times(CYTHON_UNUSED PyObject *__pyx_self,
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("times", 0);
 
-  /* "pywrapfst.pyx":508
+  /* "pywrapfst.pyx":493
  *     FstBadWeightError: Invalid weight.
  *   """
  *   cdef Weight result = _times(lhs, rhs)             # <<<<<<<<<<<<<<
  *   result._check_weight()
  *   return result
  */
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__times(__pyx_v_lhs, __pyx_v_rhs)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 508, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__times(__pyx_v_lhs, __pyx_v_rhs)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 493, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":509
+  /* "pywrapfst.pyx":494
  *   """
  *   cdef Weight result = _times(lhs, rhs)
  *   result._check_weight()             # <<<<<<<<<<<<<<
@@ -7356,11 +6985,11 @@ static PyObject *__pyx_pf_9pywrapfst_2times(CYTHON_UNUSED PyObject *__pyx_self,
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_weight");
-    __PYX_ERR(0, 509, __pyx_L1_error)
+    __PYX_ERR(0, 494, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_result->__pyx_vtab)->_check_weight(__pyx_v_result); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 509, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_result->__pyx_vtab)->_check_weight(__pyx_v_result); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 494, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":510
+  /* "pywrapfst.pyx":495
  *   cdef Weight result = _times(lhs, rhs)
  *   result._check_weight()
  *   return result             # <<<<<<<<<<<<<<
@@ -7372,7 +7001,7 @@ static PyObject *__pyx_pf_9pywrapfst_2times(CYTHON_UNUSED PyObject *__pyx_self,
   __pyx_r = ((PyObject *)__pyx_v_result);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":488
+  /* "pywrapfst.pyx":473
  * 
  * 
  * def times(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7392,7 +7021,7 @@ static PyObject *__pyx_pf_9pywrapfst_2times(CYTHON_UNUSED PyObject *__pyx_self,
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":513
+/* "pywrapfst.pyx":498
  * 
  * 
  * cdef Weight _divide(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7407,19 +7036,19 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__divide(struct __p
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("_divide", 0);
 
-  /* "pywrapfst.pyx":514
+  /* "pywrapfst.pyx":499
  * 
  * cdef Weight _divide(Weight lhs, Weight rhs):
  *   cdef Weight result = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *   result._weight.reset(new fst.WeightClass(fst.Divide(deref(lhs._weight),
  *                                                       deref(rhs._weight))))
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 514, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 499, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":515
+  /* "pywrapfst.pyx":500
  * cdef Weight _divide(Weight lhs, Weight rhs):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Divide(deref(lhs._weight),             # <<<<<<<<<<<<<<
@@ -7428,14 +7057,14 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__divide(struct __p
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 515, __pyx_L1_error)
+    __PYX_ERR(0, 500, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_lhs) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 515, __pyx_L1_error)
+    __PYX_ERR(0, 500, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":516
+  /* "pywrapfst.pyx":501
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Divide(deref(lhs._weight),
  *                                                       deref(rhs._weight))))             # <<<<<<<<<<<<<<
@@ -7444,10 +7073,10 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__divide(struct __p
  */
   if (unlikely(((PyObject *)__pyx_v_rhs) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 516, __pyx_L1_error)
+    __PYX_ERR(0, 501, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":515
+  /* "pywrapfst.pyx":500
  * cdef Weight _divide(Weight lhs, Weight rhs):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Divide(deref(lhs._weight),             # <<<<<<<<<<<<<<
@@ -7456,7 +7085,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__divide(struct __p
  */
   __pyx_v_result->_weight.reset(new fst::script::WeightClass(fst::script::Divide((*__pyx_v_lhs->_weight), (*__pyx_v_rhs->_weight))));
 
-  /* "pywrapfst.pyx":517
+  /* "pywrapfst.pyx":502
  *   result._weight.reset(new fst.WeightClass(fst.Divide(deref(lhs._weight),
  *                                                       deref(rhs._weight))))
  *   return result             # <<<<<<<<<<<<<<
@@ -7468,7 +7097,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__divide(struct __p
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":513
+  /* "pywrapfst.pyx":498
  * 
  * 
  * cdef Weight _divide(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7488,7 +7117,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__divide(struct __p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":520
+/* "pywrapfst.pyx":505
  * 
  * 
  * def divide(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7499,7 +7128,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__divide(struct __p
 /* Python wrapper */
 static PyObject *__pyx_pw_9pywrapfst_5divide(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static char __pyx_doc_9pywrapfst_4divide[] = "\n  divide(lhs, rhs)\n\n  Computes the quotient of two Weights in the same semiring.\n\n  This function computes lhs \\oslash rhs, raising an exception if lhs and rhs\n  are not in the same semiring. As there is no way to specify whether to use\n  left vs. right division, this assumes a commutative semiring in which these\n  are equivalent operations.\n\n  Args:\n     lhs: Left-hand side Weight.\n     rhs: Right-hand side Weight.\n\n  Returns:\n    A Weight object.\n\n  Raises:\n    FstArgError: Weight type not found (or not in same semiring).\n    FstBadWeightError: Invalid weight.\n  ";
-static PyMethodDef __pyx_mdef_9pywrapfst_5divide = {"divide", (PyCFunction)__pyx_pw_9pywrapfst_5divide, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_4divide};
+static PyMethodDef __pyx_mdef_9pywrapfst_5divide = {"divide", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_5divide, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_4divide};
 static PyObject *__pyx_pw_9pywrapfst_5divide(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst_Weight *__pyx_v_lhs = 0;
   struct __pyx_obj_9pywrapfst_Weight *__pyx_v_rhs = 0;
@@ -7529,11 +7158,11 @@ static PyObject *__pyx_pw_9pywrapfst_5divide(PyObject *__pyx_self, PyObject *__p
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rhs)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("divide", 1, 2, 2, 1); __PYX_ERR(0, 520, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("divide", 1, 2, 2, 1); __PYX_ERR(0, 505, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "divide") < 0)) __PYX_ERR(0, 520, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "divide") < 0)) __PYX_ERR(0, 505, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -7546,14 +7175,14 @@ static PyObject *__pyx_pw_9pywrapfst_5divide(PyObject *__pyx_self, PyObject *__p
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("divide", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 520, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("divide", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 505, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.divide", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lhs), __pyx_ptype_9pywrapfst_Weight, 1, "lhs", 0))) __PYX_ERR(0, 520, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_rhs), __pyx_ptype_9pywrapfst_Weight, 1, "rhs", 0))) __PYX_ERR(0, 520, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lhs), __pyx_ptype_9pywrapfst_Weight, 1, "lhs", 0))) __PYX_ERR(0, 505, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_rhs), __pyx_ptype_9pywrapfst_Weight, 1, "rhs", 0))) __PYX_ERR(0, 505, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_4divide(__pyx_self, __pyx_v_lhs, __pyx_v_rhs);
 
   /* function exit code */
@@ -7572,19 +7201,19 @@ static PyObject *__pyx_pf_9pywrapfst_4divide(CYTHON_UNUSED PyObject *__pyx_self,
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("divide", 0);
 
-  /* "pywrapfst.pyx":542
+  /* "pywrapfst.pyx":527
  *     FstBadWeightError: Invalid weight.
  *   """
  *   cdef Weight result = _divide(lhs, rhs)             # <<<<<<<<<<<<<<
  *   result._check_weight()
  *   return result
  */
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__divide(__pyx_v_lhs, __pyx_v_rhs)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 542, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__divide(__pyx_v_lhs, __pyx_v_rhs)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 527, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":543
+  /* "pywrapfst.pyx":528
  *   """
  *   cdef Weight result = _divide(lhs, rhs)
  *   result._check_weight()             # <<<<<<<<<<<<<<
@@ -7593,11 +7222,11 @@ static PyObject *__pyx_pf_9pywrapfst_4divide(CYTHON_UNUSED PyObject *__pyx_self,
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_weight");
-    __PYX_ERR(0, 543, __pyx_L1_error)
+    __PYX_ERR(0, 528, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_result->__pyx_vtab)->_check_weight(__pyx_v_result); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 543, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_result->__pyx_vtab)->_check_weight(__pyx_v_result); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 528, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":544
+  /* "pywrapfst.pyx":529
  *   cdef Weight result = _divide(lhs, rhs)
  *   result._check_weight()
  *   return result             # <<<<<<<<<<<<<<
@@ -7609,7 +7238,7 @@ static PyObject *__pyx_pf_9pywrapfst_4divide(CYTHON_UNUSED PyObject *__pyx_self,
   __pyx_r = ((PyObject *)__pyx_v_result);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":520
+  /* "pywrapfst.pyx":505
  * 
  * 
  * def divide(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
@@ -7629,7 +7258,7 @@ static PyObject *__pyx_pf_9pywrapfst_4divide(CYTHON_UNUSED PyObject *__pyx_self,
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":547
+/* "pywrapfst.pyx":532
  * 
  * 
  * cdef Weight _power(Weight w, size_t n):             # <<<<<<<<<<<<<<
@@ -7644,19 +7273,19 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__power(struct __py
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("_power", 0);
 
-  /* "pywrapfst.pyx":548
+  /* "pywrapfst.pyx":533
  * 
  * cdef Weight _power(Weight w, size_t n):
  *   cdef Weight result = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *   result._weight.reset(new fst.WeightClass(fst.Power(deref(w._weight), n)))
  *   return result
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 548, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 533, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":549
+  /* "pywrapfst.pyx":534
  * cdef Weight _power(Weight w, size_t n):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Power(deref(w._weight), n)))             # <<<<<<<<<<<<<<
@@ -7665,15 +7294,15 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__power(struct __py
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 549, __pyx_L1_error)
+    __PYX_ERR(0, 534, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_w) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 549, __pyx_L1_error)
+    __PYX_ERR(0, 534, __pyx_L1_error)
   }
   __pyx_v_result->_weight.reset(new fst::script::WeightClass(fst::script::Power((*__pyx_v_w->_weight), __pyx_v_n)));
 
-  /* "pywrapfst.pyx":550
+  /* "pywrapfst.pyx":535
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.Power(deref(w._weight), n)))
  *   return result             # <<<<<<<<<<<<<<
@@ -7685,7 +7314,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__power(struct __py
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":547
+  /* "pywrapfst.pyx":532
  * 
  * 
  * cdef Weight _power(Weight w, size_t n):             # <<<<<<<<<<<<<<
@@ -7705,7 +7334,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__power(struct __py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":553
+/* "pywrapfst.pyx":538
  * 
  * 
  * def power(Weight w, size_t n):             # <<<<<<<<<<<<<<
@@ -7716,7 +7345,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__power(struct __py
 /* Python wrapper */
 static PyObject *__pyx_pw_9pywrapfst_7power(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static char __pyx_doc_9pywrapfst_6power[] = "\n  power(lhs, rhs)\n\n  Computes the iterated product of a weight.\n\n  Args:\n     w: The weight.\n     n: The power.\n\n  Returns:\n    A Weight object.\n\n  Raises:\n    FstArgError: Weight type not found (or not in same semiring).\n    FstBadWeightError: Invalid weight.\n  ";
-static PyMethodDef __pyx_mdef_9pywrapfst_7power = {"power", (PyCFunction)__pyx_pw_9pywrapfst_7power, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_6power};
+static PyMethodDef __pyx_mdef_9pywrapfst_7power = {"power", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_7power, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_6power};
 static PyObject *__pyx_pw_9pywrapfst_7power(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst_Weight *__pyx_v_w = 0;
   size_t __pyx_v_n;
@@ -7746,11 +7375,11 @@ static PyObject *__pyx_pw_9pywrapfst_7power(PyObject *__pyx_self, PyObject *__py
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_n)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("power", 1, 2, 2, 1); __PYX_ERR(0, 553, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("power", 1, 2, 2, 1); __PYX_ERR(0, 538, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "power") < 0)) __PYX_ERR(0, 553, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "power") < 0)) __PYX_ERR(0, 538, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -7759,17 +7388,17 @@ static PyObject *__pyx_pw_9pywrapfst_7power(PyObject *__pyx_self, PyObject *__py
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
     __pyx_v_w = ((struct __pyx_obj_9pywrapfst_Weight *)values[0]);
-    __pyx_v_n = __Pyx_PyInt_As_size_t(values[1]); if (unlikely((__pyx_v_n == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 553, __pyx_L3_error)
+    __pyx_v_n = __Pyx_PyInt_As_size_t(values[1]); if (unlikely((__pyx_v_n == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 538, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("power", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 553, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("power", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 538, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.power", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w), __pyx_ptype_9pywrapfst_Weight, 1, "w", 0))) __PYX_ERR(0, 553, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_w), __pyx_ptype_9pywrapfst_Weight, 1, "w", 0))) __PYX_ERR(0, 538, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_6power(__pyx_self, __pyx_v_w, __pyx_v_n);
 
   /* function exit code */
@@ -7788,19 +7417,19 @@ static PyObject *__pyx_pf_9pywrapfst_6power(CYTHON_UNUSED PyObject *__pyx_self,
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("power", 0);
 
-  /* "pywrapfst.pyx":570
+  /* "pywrapfst.pyx":555
  *     FstBadWeightError: Invalid weight.
  *   """
  *   cdef Weight result = _power(w, n)             # <<<<<<<<<<<<<<
  *   result._check_weight()
  *   return result
  */
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__power(__pyx_v_w, __pyx_v_n)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 570, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__power(__pyx_v_w, __pyx_v_n)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 555, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":571
+  /* "pywrapfst.pyx":556
  *   """
  *   cdef Weight result = _power(w, n)
  *   result._check_weight()             # <<<<<<<<<<<<<<
@@ -7809,11 +7438,11 @@ static PyObject *__pyx_pf_9pywrapfst_6power(CYTHON_UNUSED PyObject *__pyx_self,
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_weight");
-    __PYX_ERR(0, 571, __pyx_L1_error)
+    __PYX_ERR(0, 556, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_result->__pyx_vtab)->_check_weight(__pyx_v_result); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 571, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_result->__pyx_vtab)->_check_weight(__pyx_v_result); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 556, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":572
+  /* "pywrapfst.pyx":557
  *   cdef Weight result = _power(w, n)
  *   result._check_weight()
  *   return result             # <<<<<<<<<<<<<<
@@ -7825,7 +7454,7 @@ static PyObject *__pyx_pf_9pywrapfst_6power(CYTHON_UNUSED PyObject *__pyx_self,
   __pyx_r = ((PyObject *)__pyx_v_result);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":553
+  /* "pywrapfst.pyx":538
  * 
  * 
  * def power(Weight w, size_t n):             # <<<<<<<<<<<<<<
@@ -7845,7 +7474,7 @@ static PyObject *__pyx_pf_9pywrapfst_6power(CYTHON_UNUSED PyObject *__pyx_self,
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":575
+/* "pywrapfst.pyx":560
  * 
  * 
  * cdef fst.WeightClass _get_WeightClass_or_Zero(const string &weight_type,             # <<<<<<<<<<<<<<
@@ -7864,10 +7493,9 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_get_WeightClass_or_Zero", 0);
 
-  /* "pywrapfst.pyx":593
+  /* "pywrapfst.pyx":578
  *   """
  *   cdef fst.WeightClass result
  *   if weight is None:             # <<<<<<<<<<<<<<
@@ -7878,7 +7506,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
   __pyx_t_2 = (__pyx_t_1 != 0);
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":594
+    /* "pywrapfst.pyx":579
  *   cdef fst.WeightClass result
  *   if weight is None:
  *     result = fst.WeightClass.Zero(weight_type)             # <<<<<<<<<<<<<<
@@ -7887,7 +7515,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
  */
     __pyx_v_result = fst::script::WeightClass::Zero(__pyx_v_weight_type);
 
-    /* "pywrapfst.pyx":593
+    /* "pywrapfst.pyx":578
  *   """
  *   cdef fst.WeightClass result
  *   if weight is None:             # <<<<<<<<<<<<<<
@@ -7897,7 +7525,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
     goto __pyx_L3;
   }
 
-  /* "pywrapfst.pyx":595
+  /* "pywrapfst.pyx":580
  *   if weight is None:
  *     result = fst.WeightClass.Zero(weight_type)
  *   elif isinstance(weight, Weight):             # <<<<<<<<<<<<<<
@@ -7908,7 +7536,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
   __pyx_t_1 = (__pyx_t_2 != 0);
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":596
+    /* "pywrapfst.pyx":581
  *     result = fst.WeightClass.Zero(weight_type)
  *   elif isinstance(weight, Weight):
  *     result = deref(<fst.WeightClass *> (<Weight> weight)._weight.get())             # <<<<<<<<<<<<<<
@@ -7917,11 +7545,11 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
  */
     if (unlikely(__pyx_v_weight == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-      __PYX_ERR(0, 596, __pyx_L1_error)
+      __PYX_ERR(0, 581, __pyx_L1_error)
     }
     __pyx_v_result = (*((fst::script::WeightClass *)((struct __pyx_obj_9pywrapfst_Weight *)__pyx_v_weight)->_weight.get()));
 
-    /* "pywrapfst.pyx":595
+    /* "pywrapfst.pyx":580
  *   if weight is None:
  *     result = fst.WeightClass.Zero(weight_type)
  *   elif isinstance(weight, Weight):             # <<<<<<<<<<<<<<
@@ -7931,7 +7559,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
     goto __pyx_L3;
   }
 
-  /* "pywrapfst.pyx":598
+  /* "pywrapfst.pyx":583
  *     result = deref(<fst.WeightClass *> (<Weight> weight)._weight.get())
  *   else:
  *     result = fst.WeightClass(weight_type, weight_tostring(weight))             # <<<<<<<<<<<<<<
@@ -7939,10 +7567,10 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
  *       raise FstBadWeightError(weight_tostring(weight))
  */
   /*else*/ {
-    __pyx_t_3 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 598, __pyx_L1_error)
+    __pyx_t_3 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 583, __pyx_L1_error)
     __pyx_v_result = fst::script::WeightClass(__pyx_v_weight_type, __pyx_t_3);
 
-    /* "pywrapfst.pyx":599
+    /* "pywrapfst.pyx":584
  *   else:
  *     result = fst.WeightClass(weight_type, weight_tostring(weight))
  *     if result.ToString() == b"BadNumber":             # <<<<<<<<<<<<<<
@@ -7952,17 +7580,17 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
     __pyx_t_1 = ((__pyx_v_result.ToString() == ((char const *)"BadNumber")) != 0);
     if (unlikely(__pyx_t_1)) {
 
-      /* "pywrapfst.pyx":600
+      /* "pywrapfst.pyx":585
  *     result = fst.WeightClass(weight_type, weight_tostring(weight))
  *     if result.ToString() == b"BadNumber":
  *       raise FstBadWeightError(weight_tostring(weight))             # <<<<<<<<<<<<<<
  *   return result
  * 
  */
-      __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstBadWeightError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 600, __pyx_L1_error)
+      __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_FstBadWeightError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 585, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 600, __pyx_L1_error)
-      __pyx_t_6 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 600, __pyx_L1_error)
+      __pyx_t_3 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 585, __pyx_L1_error)
+      __pyx_t_6 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 585, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_6);
       __pyx_t_7 = NULL;
       if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
@@ -7974,47 +7602,17 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
           __Pyx_DECREF_SET(__pyx_t_5, function);
         }
       }
-      if (!__pyx_t_7) {
-        __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 600, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_5)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-          __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 600, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-          __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-          __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 600, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-          __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 600, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_8);
-          __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-          __Pyx_GIVEREF(__pyx_t_6);
-          PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_6);
-          __pyx_t_6 = 0;
-          __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 600, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        }
-      }
+      __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 585, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __Pyx_Raise(__pyx_t_4, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __PYX_ERR(0, 600, __pyx_L1_error)
+      __PYX_ERR(0, 585, __pyx_L1_error)
 
-      /* "pywrapfst.pyx":599
+      /* "pywrapfst.pyx":584
  *   else:
  *     result = fst.WeightClass(weight_type, weight_tostring(weight))
  *     if result.ToString() == b"BadNumber":             # <<<<<<<<<<<<<<
@@ -8025,7 +7623,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
   }
   __pyx_L3:;
 
-  /* "pywrapfst.pyx":601
+  /* "pywrapfst.pyx":586
  *     if result.ToString() == b"BadNumber":
  *       raise FstBadWeightError(weight_tostring(weight))
  *   return result             # <<<<<<<<<<<<<<
@@ -8035,7 +7633,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":575
+  /* "pywrapfst.pyx":560
  * 
  * 
  * cdef fst.WeightClass _get_WeightClass_or_Zero(const string &weight_type,             # <<<<<<<<<<<<<<
@@ -8049,7 +7647,6 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._get_WeightClass_or_Zero", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_pretend_to_initialize(&__pyx_r);
   __pyx_L0:;
@@ -8057,7 +7654,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_Zero(std:
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":604
+/* "pywrapfst.pyx":589
  * 
  * 
  * cdef fst.WeightClass _get_WeightClass_or_One(const string &weight_type,             # <<<<<<<<<<<<<<
@@ -8076,10 +7673,9 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_get_WeightClass_or_One", 0);
 
-  /* "pywrapfst.pyx":622
+  /* "pywrapfst.pyx":607
  *   """
  *   cdef fst.WeightClass result
  *   if weight is None:             # <<<<<<<<<<<<<<
@@ -8090,7 +7686,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
   __pyx_t_2 = (__pyx_t_1 != 0);
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":623
+    /* "pywrapfst.pyx":608
  *   cdef fst.WeightClass result
  *   if weight is None:
  *     result = fst.WeightClass.One(weight_type)             # <<<<<<<<<<<<<<
@@ -8099,7 +7695,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
  */
     __pyx_v_result = fst::script::WeightClass::One(__pyx_v_weight_type);
 
-    /* "pywrapfst.pyx":622
+    /* "pywrapfst.pyx":607
  *   """
  *   cdef fst.WeightClass result
  *   if weight is None:             # <<<<<<<<<<<<<<
@@ -8109,7 +7705,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
     goto __pyx_L3;
   }
 
-  /* "pywrapfst.pyx":624
+  /* "pywrapfst.pyx":609
  *   if weight is None:
  *     result = fst.WeightClass.One(weight_type)
  *   elif isinstance(weight, Weight):             # <<<<<<<<<<<<<<
@@ -8120,7 +7716,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
   __pyx_t_1 = (__pyx_t_2 != 0);
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":625
+    /* "pywrapfst.pyx":610
  *     result = fst.WeightClass.One(weight_type)
  *   elif isinstance(weight, Weight):
  *     result = deref(<fst.WeightClass *> (<Weight> weight)._weight.get())             # <<<<<<<<<<<<<<
@@ -8129,11 +7725,11 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
  */
     if (unlikely(__pyx_v_weight == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-      __PYX_ERR(0, 625, __pyx_L1_error)
+      __PYX_ERR(0, 610, __pyx_L1_error)
     }
     __pyx_v_result = (*((fst::script::WeightClass *)((struct __pyx_obj_9pywrapfst_Weight *)__pyx_v_weight)->_weight.get()));
 
-    /* "pywrapfst.pyx":624
+    /* "pywrapfst.pyx":609
  *   if weight is None:
  *     result = fst.WeightClass.One(weight_type)
  *   elif isinstance(weight, Weight):             # <<<<<<<<<<<<<<
@@ -8143,7 +7739,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
     goto __pyx_L3;
   }
 
-  /* "pywrapfst.pyx":627
+  /* "pywrapfst.pyx":612
  *     result = deref(<fst.WeightClass *> (<Weight> weight)._weight.get())
  *   else:
  *     result = fst.WeightClass(weight_type, weight_tostring(weight))             # <<<<<<<<<<<<<<
@@ -8151,10 +7747,10 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
  *       raise FstBadWeightError(weight_tostring(weight))
  */
   /*else*/ {
-    __pyx_t_3 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 627, __pyx_L1_error)
+    __pyx_t_3 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 612, __pyx_L1_error)
     __pyx_v_result = fst::script::WeightClass(__pyx_v_weight_type, __pyx_t_3);
 
-    /* "pywrapfst.pyx":628
+    /* "pywrapfst.pyx":613
  *   else:
  *     result = fst.WeightClass(weight_type, weight_tostring(weight))
  *     if result.ToString() == b"BadNumber":             # <<<<<<<<<<<<<<
@@ -8164,17 +7760,17 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
     __pyx_t_1 = ((__pyx_v_result.ToString() == ((char const *)"BadNumber")) != 0);
     if (unlikely(__pyx_t_1)) {
 
-      /* "pywrapfst.pyx":629
+      /* "pywrapfst.pyx":614
  *     result = fst.WeightClass(weight_type, weight_tostring(weight))
  *     if result.ToString() == b"BadNumber":
  *       raise FstBadWeightError(weight_tostring(weight))             # <<<<<<<<<<<<<<
  *   return result
  * 
  */
-      __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstBadWeightError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 629, __pyx_L1_error)
+      __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_FstBadWeightError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 614, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_3 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 629, __pyx_L1_error)
-      __pyx_t_6 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 629, __pyx_L1_error)
+      __pyx_t_3 = __pyx_f_9pywrapfst_weight_tostring(__pyx_v_weight, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 614, __pyx_L1_error)
+      __pyx_t_6 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 614, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_6);
       __pyx_t_7 = NULL;
       if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
@@ -8186,47 +7782,17 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
           __Pyx_DECREF_SET(__pyx_t_5, function);
         }
       }
-      if (!__pyx_t_7) {
-        __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 629, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_5)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-          __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 629, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-          __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-          __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 629, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-          __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 629, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_8);
-          __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-          __Pyx_GIVEREF(__pyx_t_6);
-          PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_6);
-          __pyx_t_6 = 0;
-          __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 629, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        }
-      }
+      __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 614, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_4);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __Pyx_Raise(__pyx_t_4, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __PYX_ERR(0, 629, __pyx_L1_error)
+      __PYX_ERR(0, 614, __pyx_L1_error)
 
-      /* "pywrapfst.pyx":628
+      /* "pywrapfst.pyx":613
  *   else:
  *     result = fst.WeightClass(weight_type, weight_tostring(weight))
  *     if result.ToString() == b"BadNumber":             # <<<<<<<<<<<<<<
@@ -8237,7 +7803,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
   }
   __pyx_L3:;
 
-  /* "pywrapfst.pyx":630
+  /* "pywrapfst.pyx":615
  *     if result.ToString() == b"BadNumber":
  *       raise FstBadWeightError(weight_tostring(weight))
  *   return result             # <<<<<<<<<<<<<<
@@ -8247,7 +7813,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":604
+  /* "pywrapfst.pyx":589
  * 
  * 
  * cdef fst.WeightClass _get_WeightClass_or_One(const string &weight_type,             # <<<<<<<<<<<<<<
@@ -8261,7 +7827,6 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._get_WeightClass_or_One", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_pretend_to_initialize(&__pyx_r);
   __pyx_L0:;
@@ -8269,7 +7834,7 @@ static fst::script::WeightClass __pyx_f_9pywrapfst__get_WeightClass_or_One(std::
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":633
+/* "pywrapfst.pyx":618
  * 
  * 
  * cdef Weight _Zero(weight_type):             # <<<<<<<<<<<<<<
@@ -8285,21 +7850,22 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__Zero(PyObject *__
   std::string __pyx_t_2;
   int __pyx_t_3;
   PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("_Zero", 0);
 
-  /* "pywrapfst.pyx":634
+  /* "pywrapfst.pyx":619
  * 
  * cdef Weight _Zero(weight_type):
  *   cdef Weight result = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *   result._weight.reset(new fst.WeightClass(fst.WeightClass.Zero(
  *       tostring(weight_type))))
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 634, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 619, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":635
+  /* "pywrapfst.pyx":620
  * cdef Weight _Zero(weight_type):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.WeightClass.Zero(             # <<<<<<<<<<<<<<
@@ -8308,19 +7874,19 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__Zero(PyObject *__
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 635, __pyx_L1_error)
+    __PYX_ERR(0, 620, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":636
+  /* "pywrapfst.pyx":621
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.WeightClass.Zero(
  *       tostring(weight_type))))             # <<<<<<<<<<<<<<
  *   if result._weight.get().Type() == b"none":
  *     raise FstArgError("Weight type not found")
  */
-  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_weight_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 636, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_weight_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 621, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":635
+  /* "pywrapfst.pyx":620
  * cdef Weight _Zero(weight_type):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(fst.WeightClass.Zero(             # <<<<<<<<<<<<<<
@@ -8329,7 +7895,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__Zero(PyObject *__
  */
   __pyx_v_result->_weight.reset(new fst::script::WeightClass(fst::script::WeightClass::Zero(__pyx_t_2)));
 
-  /* "pywrapfst.pyx":637
+  /* "pywrapfst.pyx":622
  *   result._weight.reset(new fst.WeightClass(fst.WeightClass.Zero(
  *       tostring(weight_type))))
  *   if result._weight.get().Type() == b"none":             # <<<<<<<<<<<<<<
@@ -8338,28 +7904,40 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__Zero(PyObject *__
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 637, __pyx_L1_error)
+    __PYX_ERR(0, 622, __pyx_L1_error)
   }
   __pyx_t_3 = ((__pyx_v_result->_weight.get()->Type() == ((char const *)"none")) != 0);
   if (unlikely(__pyx_t_3)) {
 
-    /* "pywrapfst.pyx":638
+    /* "pywrapfst.pyx":623
  *       tostring(weight_type))))
  *   if result._weight.get().Type() == b"none":
  *     raise FstArgError("Weight type not found")             # <<<<<<<<<<<<<<
  *   return result
  * 
  */
-    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 638, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 638, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 623, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_u_Weight_type_not_found) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_u_Weight_type_not_found);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 623, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __PYX_ERR(0, 638, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 623, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":637
+    /* "pywrapfst.pyx":622
  *   result._weight.reset(new fst.WeightClass(fst.WeightClass.Zero(
  *       tostring(weight_type))))
  *   if result._weight.get().Type() == b"none":             # <<<<<<<<<<<<<<
@@ -8368,7 +7946,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__Zero(PyObject *__
  */
   }
 
-  /* "pywrapfst.pyx":639
+  /* "pywrapfst.pyx":624
  *   if result._weight.get().Type() == b"none":
  *     raise FstArgError("Weight type not found")
  *   return result             # <<<<<<<<<<<<<<
@@ -8380,7 +7958,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__Zero(PyObject *__
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":633
+  /* "pywrapfst.pyx":618
  * 
  * 
  * cdef Weight _Zero(weight_type):             # <<<<<<<<<<<<<<
@@ -8392,6 +7970,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__Zero(PyObject *__
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst._Zero", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -8401,7 +7980,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__Zero(PyObject *__
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":642
+/* "pywrapfst.pyx":627
  * 
  * 
  * cdef Weight _One(weight_type):             # <<<<<<<<<<<<<<
@@ -8417,21 +7996,22 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__One(PyObject *__p
   std::string __pyx_t_2;
   int __pyx_t_3;
   PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("_One", 0);
 
-  /* "pywrapfst.pyx":643
+  /* "pywrapfst.pyx":628
  * 
  * cdef Weight _One(weight_type):
  *   cdef Weight result = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *   result._weight.reset(new fst.WeightClass(
  *         fst.WeightClass.One(tostring(weight_type))))
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 643, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 628, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":644
+  /* "pywrapfst.pyx":629
  * cdef Weight _One(weight_type):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(             # <<<<<<<<<<<<<<
@@ -8440,19 +8020,19 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__One(PyObject *__p
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 644, __pyx_L1_error)
+    __PYX_ERR(0, 629, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":645
+  /* "pywrapfst.pyx":630
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(
  *         fst.WeightClass.One(tostring(weight_type))))             # <<<<<<<<<<<<<<
  *   if result._weight.get().Type() == b"none":
  *     raise FstArgError("Weight type not found")
  */
-  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_weight_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 645, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_weight_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 630, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":644
+  /* "pywrapfst.pyx":629
  * cdef Weight _One(weight_type):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(             # <<<<<<<<<<<<<<
@@ -8461,7 +8041,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__One(PyObject *__p
  */
   __pyx_v_result->_weight.reset(new fst::script::WeightClass(fst::script::WeightClass::One(__pyx_t_2)));
 
-  /* "pywrapfst.pyx":646
+  /* "pywrapfst.pyx":631
  *   result._weight.reset(new fst.WeightClass(
  *         fst.WeightClass.One(tostring(weight_type))))
  *   if result._weight.get().Type() == b"none":             # <<<<<<<<<<<<<<
@@ -8470,28 +8050,40 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__One(PyObject *__p
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 646, __pyx_L1_error)
+    __PYX_ERR(0, 631, __pyx_L1_error)
   }
   __pyx_t_3 = ((__pyx_v_result->_weight.get()->Type() == ((char const *)"none")) != 0);
   if (unlikely(__pyx_t_3)) {
 
-    /* "pywrapfst.pyx":647
+    /* "pywrapfst.pyx":632
  *         fst.WeightClass.One(tostring(weight_type))))
  *   if result._weight.get().Type() == b"none":
  *     raise FstArgError("Weight type not found")             # <<<<<<<<<<<<<<
  *   return result
  * 
  */
-    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 647, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 647, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 632, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_u_Weight_type_not_found) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_u_Weight_type_not_found);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 632, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __PYX_ERR(0, 647, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 632, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":646
+    /* "pywrapfst.pyx":631
  *   result._weight.reset(new fst.WeightClass(
  *         fst.WeightClass.One(tostring(weight_type))))
  *   if result._weight.get().Type() == b"none":             # <<<<<<<<<<<<<<
@@ -8500,7 +8092,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__One(PyObject *__p
  */
   }
 
-  /* "pywrapfst.pyx":648
+  /* "pywrapfst.pyx":633
  *   if result._weight.get().Type() == b"none":
  *     raise FstArgError("Weight type not found")
  *   return result             # <<<<<<<<<<<<<<
@@ -8512,7 +8104,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__One(PyObject *__p
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":642
+  /* "pywrapfst.pyx":627
  * 
  * 
  * cdef Weight _One(weight_type):             # <<<<<<<<<<<<<<
@@ -8524,6 +8116,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__One(PyObject *__p
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst._One", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -8533,7 +8126,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__One(PyObject *__p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":651
+/* "pywrapfst.pyx":636
  * 
  * 
  * cdef Weight _NoWeight(weight_type):             # <<<<<<<<<<<<<<
@@ -8549,19 +8142,19 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__NoWeight(PyObject
   std::string __pyx_t_2;
   __Pyx_RefNannySetupContext("_NoWeight", 0);
 
-  /* "pywrapfst.pyx":652
+  /* "pywrapfst.pyx":637
  * 
  * cdef Weight _NoWeight(weight_type):
  *   cdef Weight result = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *   result._weight.reset(new fst.WeightClass(
  *         fst.WeightClass.NoWeight(tostring(weight_type))))
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 652, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 637, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":653
+  /* "pywrapfst.pyx":638
  * cdef Weight _NoWeight(weight_type):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(             # <<<<<<<<<<<<<<
@@ -8570,19 +8163,19 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__NoWeight(PyObject
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 653, __pyx_L1_error)
+    __PYX_ERR(0, 638, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":654
+  /* "pywrapfst.pyx":639
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(
  *         fst.WeightClass.NoWeight(tostring(weight_type))))             # <<<<<<<<<<<<<<
  *   return result
  * 
  */
-  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_weight_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 654, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_weight_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 639, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":653
+  /* "pywrapfst.pyx":638
  * cdef Weight _NoWeight(weight_type):
  *   cdef Weight result = Weight.__new__(Weight)
  *   result._weight.reset(new fst.WeightClass(             # <<<<<<<<<<<<<<
@@ -8591,7 +8184,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__NoWeight(PyObject
  */
   __pyx_v_result->_weight.reset(new fst::script::WeightClass(fst::script::WeightClass::NoWeight(__pyx_t_2)));
 
-  /* "pywrapfst.pyx":655
+  /* "pywrapfst.pyx":640
  *   result._weight.reset(new fst.WeightClass(
  *         fst.WeightClass.NoWeight(tostring(weight_type))))
  *   return result             # <<<<<<<<<<<<<<
@@ -8603,7 +8196,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__NoWeight(PyObject
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":651
+  /* "pywrapfst.pyx":636
  * 
  * 
  * cdef Weight _NoWeight(weight_type):             # <<<<<<<<<<<<<<
@@ -8623,7 +8216,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst__NoWeight(PyObject
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":689
+/* "pywrapfst.pyx":674
  *   # Doing so will allow undefined behavior.
  * 
  *   def __init__(self):             # <<<<<<<<<<<<<<
@@ -8656,31 +8249,30 @@ static int __pyx_pf_9pywrapfst_12_SymbolTable___init__(struct __pyx_obj_9pywrapf
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
-  PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":690
+  /* "pywrapfst.pyx":675
  * 
  *   def __init__(self):
  *     raise FstDeletedConstructorError(             # <<<<<<<<<<<<<<
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstDeletedConstructorError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 690, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstDeletedConstructorError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 675, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
 
-  /* "pywrapfst.pyx":691
+  /* "pywrapfst.pyx":676
  *   def __init__(self):
  *     raise FstDeletedConstructorError(
  *         "Cannot construct {}".format(self.__class__.__name__))             # <<<<<<<<<<<<<<
  * 
  *   def __iter__(self):
  */
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Cannot_construct, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 691, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Cannot_construct, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 676, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_class); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 691, __pyx_L1_error)
+  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_class); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 676, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 691, __pyx_L1_error)
+  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 676, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __pyx_t_5 = NULL;
@@ -8693,41 +8285,11 @@ static int __pyx_pf_9pywrapfst_12_SymbolTable___init__(struct __pyx_obj_9pywrapf
       __Pyx_DECREF_SET(__pyx_t_4, function);
     }
   }
-  if (!__pyx_t_5) {
-    __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 691, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_GOTREF(__pyx_t_3);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_6};
-      __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 691, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_6};
-      __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 691, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 691, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
-      __Pyx_GIVEREF(__pyx_t_6);
-      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_t_6);
-      __pyx_t_6 = 0;
-      __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 691, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    }
-  }
+  __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 676, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
@@ -8739,47 +8301,17 @@ static int __pyx_pf_9pywrapfst_12_SymbolTable___init__(struct __pyx_obj_9pywrapf
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 690, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 690, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 690, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 690, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 690, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 675, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(0, 690, __pyx_L1_error)
+  __PYX_ERR(0, 675, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":689
+  /* "pywrapfst.pyx":674
  *   # Doing so will allow undefined behavior.
  * 
  *   def __init__(self):             # <<<<<<<<<<<<<<
@@ -8795,14 +8327,13 @@ static int __pyx_pf_9pywrapfst_12_SymbolTable___init__(struct __pyx_obj_9pywrapf
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_AddTraceback("pywrapfst._SymbolTable.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = -1;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":693
+/* "pywrapfst.pyx":678
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  *   def __iter__(self):             # <<<<<<<<<<<<<<
@@ -8829,21 +8360,21 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_2__iter__(struct __pyx_obj_9
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__iter__", 0);
 
-  /* "pywrapfst.pyx":694
+  /* "pywrapfst.pyx":679
  * 
  *   def __iter__(self):
  *     return SymbolTableIterator(self)             # <<<<<<<<<<<<<<
  * 
- *   cpdef int64 available_key(self):
+ *   # Registers the class for pickling.
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_9pywrapfst_SymbolTableIterator), ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 694, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_9pywrapfst_SymbolTableIterator), ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 679, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":693
+  /* "pywrapfst.pyx":678
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  *   def __iter__(self):             # <<<<<<<<<<<<<<
@@ -8862,15 +8393,98 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_2__iter__(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":696
- *     return SymbolTableIterator(self)
+/* "pywrapfst.pyx":683
+ *   # Registers the class for pickling.
+ * 
+ *   def __reduce__(self):             # <<<<<<<<<<<<<<
+ *     return (_read_SymbolTable_from_string, (self.write_to_string(),))
+ * 
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_5__reduce__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_5__reduce__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__reduce__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_4__reduce__(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_4__reduce__(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  __Pyx_RefNannySetupContext("__reduce__", 0);
+
+  /* "pywrapfst.pyx":684
+ * 
+ *   def __reduce__(self):
+ *     return (_read_SymbolTable_from_string, (self.write_to_string(),))             # <<<<<<<<<<<<<<
+ * 
+ *   cpdef int64 available_key(self):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_read_SymbolTable_from_string); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 684, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "write_to_string");
+    __PYX_ERR(0, 684, __pyx_L1_error)
+  }
+  __pyx_t_2 = ((struct __pyx_vtabstruct_9pywrapfst__SymbolTable *)__pyx_v_self->__pyx_vtab)->write_to_string(__pyx_v_self, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 684, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 684, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_GIVEREF(__pyx_t_2);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 684, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_1);
+  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_3);
+  PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3);
+  __pyx_t_1 = 0;
+  __pyx_t_3 = 0;
+  __pyx_r = __pyx_t_2;
+  __pyx_t_2 = 0;
+  goto __pyx_L0;
+
+  /* "pywrapfst.pyx":683
+ *   # Registers the class for pickling.
+ * 
+ *   def __reduce__(self):             # <<<<<<<<<<<<<<
+ *     return (_read_SymbolTable_from_string, (self.write_to_string(),))
+ * 
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("pywrapfst._SymbolTable.__reduce__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pywrapfst.pyx":686
+ *     return (_read_SymbolTable_from_string, (self.write_to_string(),))
  * 
  *   cpdef int64 available_key(self):             # <<<<<<<<<<<<<<
  *     """
  *     available_key(self)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_5available_key(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_7available_key(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
 static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_12_SymbolTable_available_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch) {
   __pyx_t_10basictypes_int64 __pyx_r;
   __Pyx_RefNannyDeclarations
@@ -8883,54 +8497,67 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_12_SymbolTable_available_ke
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_available_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 696, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_5available_key)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_available_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 686, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_7available_key)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 686, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 686, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 696, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 696, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 696, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":702
+  /* "pywrapfst.pyx":692
  *     Returns an integer indicating the next available key index in the table.
  *     """
  *     return self._table.AvailableKey()             # <<<<<<<<<<<<<<
  * 
- *   cpdef string checksum(self):
+ *   cpdef bytes checksum(self):
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 702, __pyx_L1_error)
+    __PYX_ERR(0, 692, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_table->AvailableKey();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":696
- *     return SymbolTableIterator(self)
+  /* "pywrapfst.pyx":686
+ *     return (_read_SymbolTable_from_string, (self.write_to_string(),))
  * 
  *   cpdef int64 available_key(self):             # <<<<<<<<<<<<<<
  *     """
@@ -8951,26 +8578,26 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_12_SymbolTable_available_ke
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_5available_key(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_4available_key[] = "\n    available_key(self)\n\n    Returns an integer indicating the next available key index in the table.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_5available_key(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_7available_key(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_6available_key[] = "\n    available_key(self)\n\n    Returns an integer indicating the next available key index in the table.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_7available_key(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("available_key (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_4available_key(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_6available_key(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_4available_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_6available_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("available_key", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_12_SymbolTable_available_key(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 696, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_12_SymbolTable_available_key(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 686, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -8987,77 +8614,94 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_4available_key(struct __pyx_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":704
+/* "pywrapfst.pyx":694
  *     return self._table.AvailableKey()
  * 
- *   cpdef string checksum(self):             # <<<<<<<<<<<<<<
+ *   cpdef bytes checksum(self):             # <<<<<<<<<<<<<<
  *     """
  *     checksum(self)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_7checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static std::string __pyx_f_9pywrapfst_12_SymbolTable_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch) {
-  std::string __pyx_r;
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_9checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_f_9pywrapfst_12_SymbolTable_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch) {
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  std::string __pyx_t_5;
   __Pyx_RefNannySetupContext("checksum", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 704, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_7checksum)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 694, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_9checksum)) {
+        __Pyx_XDECREF(__pyx_r);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 694, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(PyBytes_CheckExact(__pyx_t_2))||((__pyx_t_2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_2)->tp_name), 0))) __PYX_ERR(0, 694, __pyx_L1_error)
+        __pyx_r = ((PyObject*)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 704, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 704, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 704, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":710
- *     Returns a string indicating the label-agnostic MD5 checksum for the table.
+  /* "pywrapfst.pyx":700
+ *     Returns a bytestring indicating the label-independent MD5 checksum.
  *     """
  *     return self._table.CheckSum()             # <<<<<<<<<<<<<<
  * 
  *   cpdef SymbolTable copy(self):
  */
+  __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 710, __pyx_L1_error)
+    __PYX_ERR(0, 700, __pyx_L1_error)
   }
-  __pyx_r = __pyx_v_self->_table->CheckSum();
+  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_self->_table->CheckSum()); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 700, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":704
+  /* "pywrapfst.pyx":694
  *     return self._table.AvailableKey()
  * 
- *   cpdef string checksum(self):             # <<<<<<<<<<<<<<
+ *   cpdef bytes checksum(self):             # <<<<<<<<<<<<<<
  *     """
  *     checksum(self)
  */
@@ -9068,34 +8712,35 @@ static std::string __pyx_f_9pywrapfst_12_SymbolTable_checksum(struct __pyx_obj_9
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_WriteUnraisable("pywrapfst._SymbolTable.checksum", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
-  __Pyx_pretend_to_initialize(&__pyx_r);
+  __Pyx_AddTraceback("pywrapfst._SymbolTable.checksum", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
   __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_7checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_6checksum[] = "\n    checksum(self)\n\n    Returns a string indicating the label-agnostic MD5 checksum for the table.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_7checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_9checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_8checksum[] = "\n    checksum(self)\n\n    Returns a bytestring indicating the label-independent MD5 checksum.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_9checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("checksum (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_6checksum(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_8checksum(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_6checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_8checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("checksum", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_12_SymbolTable_checksum(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 704, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_12_SymbolTable_checksum(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 694, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -9112,7 +8757,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_6checksum(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":712
+/* "pywrapfst.pyx":702
  *     return self._table.CheckSum()
  * 
  *   cpdef SymbolTable copy(self):             # <<<<<<<<<<<<<<
@@ -9120,7 +8765,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_6checksum(struct __pyx_obj_9
  *     copy(self)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_9copy(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_11copy(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
 static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_12_SymbolTable_copy(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch) {
   struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -9132,40 +8777,53 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_12_SymbolTabl
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_copy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 712, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_9copy)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_copy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 702, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_11copy)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 702, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_SymbolTable))))) __PYX_ERR(0, 702, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst_SymbolTable *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 712, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 712, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_SymbolTable))))) __PYX_ERR(0, 712, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst_SymbolTable *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":718
+  /* "pywrapfst.pyx":708
  *     Returns a mutable copy of the SymbolTable.
  *     """
  *     return _init_SymbolTable(self._table.Copy())             # <<<<<<<<<<<<<<
@@ -9175,15 +8833,15 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_12_SymbolTabl
   __Pyx_XDECREF(((PyObject *)__pyx_r));
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 718, __pyx_L1_error)
+    __PYX_ERR(0, 708, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(__pyx_v_self->_table->Copy())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 718, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(__pyx_v_self->_table->Copy())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 708, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst_SymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":712
+  /* "pywrapfst.pyx":702
  *     return self._table.CheckSum()
  * 
  *   cpdef SymbolTable copy(self):             # <<<<<<<<<<<<<<
@@ -9206,26 +8864,26 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_12_SymbolTabl
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_9copy(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_8copy[] = "\n    copy(self)\n\n    Returns a mutable copy of the SymbolTable.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_9copy(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_11copy(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_10copy[] = "\n    copy(self)\n\n    Returns a mutable copy of the SymbolTable.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_11copy(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("copy (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_8copy(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_10copy(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_8copy(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10copy(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("copy", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_12_SymbolTable_copy(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 712, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_12_SymbolTable_copy(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 702, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -9242,7 +8900,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_8copy(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":720
+/* "pywrapfst.pyx":710
  *     return _init_SymbolTable(self._table.Copy())
  * 
  *   def find(self, key):             # <<<<<<<<<<<<<<
@@ -9251,20 +8909,20 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_8copy(struct __pyx_obj_9pywr
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_11find(PyObject *__pyx_v_self, PyObject *__pyx_v_key); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_10find[] = "\n    find(self, key)\n\n    Given a symbol or index, finds the other one.\n\n    This method returns the index associated with a symbol key, or the symbol\n    associated with a index key.\n\n    Args:\n      key: Either a string or an index.\n\n    Returns:\n      If the key is a string, the associated index or NO_LABEL if not found; if\n          the key is an integer, the associated symbol or an empty string if\n          not found.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_11find(PyObject *__pyx_v_self, PyObject *__pyx_v_key) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_13find(PyObject *__pyx_v_self, PyObject *__pyx_v_key); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_12find[] = "\n    find(self, key)\n\n    Given a symbol or index, finds the other one.\n\n    This method returns the index associated with a symbol key, or the symbol\n    associated with a index key.\n\n    Args:\n      key: Either a string or an index.\n\n    Returns:\n      If the key is a string, the associated index or NO_LABEL if not found; if\n          the key is an integer, the associated symbol or an empty string if\n          not found.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_13find(PyObject *__pyx_v_self, PyObject *__pyx_v_key) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("find (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_10find(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_key));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_12find(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_key));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_12find(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -9279,7 +8937,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
   __pyx_t_10basictypes_int64 __pyx_t_10;
   __Pyx_RefNannySetupContext("find", 0);
 
-  /* "pywrapfst.pyx":737
+  /* "pywrapfst.pyx":727
  *           not found.
  *     """
  *     try:             # <<<<<<<<<<<<<<
@@ -9295,7 +8953,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
     __Pyx_XGOTREF(__pyx_t_3);
     /*try:*/ {
 
-      /* "pywrapfst.pyx":738
+      /* "pywrapfst.pyx":728
  *     """
  *     try:
  *       return self._table.FindIndex(tostring(key))             # <<<<<<<<<<<<<<
@@ -9305,16 +8963,16 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
       __Pyx_XDECREF(__pyx_r);
       if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
         PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-        __PYX_ERR(0, 738, __pyx_L3_error)
+        __PYX_ERR(0, 728, __pyx_L3_error)
       }
-      __pyx_t_4 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 738, __pyx_L3_error)
-      __pyx_t_5 = __Pyx_PyInt_From_int64_t(__pyx_v_self->_table->Find(__pyx_t_4)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 738, __pyx_L3_error)
+      __pyx_t_4 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 728, __pyx_L3_error)
+      __pyx_t_5 = __Pyx_PyInt_From_int64_t(__pyx_v_self->_table->Find(__pyx_t_4)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 728, __pyx_L3_error)
       __Pyx_GOTREF(__pyx_t_5);
       __pyx_r = __pyx_t_5;
       __pyx_t_5 = 0;
       goto __pyx_L7_try_return;
 
-      /* "pywrapfst.pyx":737
+      /* "pywrapfst.pyx":727
  *           not found.
  *     """
  *     try:             # <<<<<<<<<<<<<<
@@ -9325,7 +8983,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
     __pyx_L3_error:;
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-    /* "pywrapfst.pyx":739
+    /* "pywrapfst.pyx":729
  *     try:
  *       return self._table.FindIndex(tostring(key))
  *     except FstArgError:             # <<<<<<<<<<<<<<
@@ -9333,7 +8991,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
  * 
  */
     __Pyx_ErrFetch(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
-    __pyx_t_8 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 739, __pyx_L5_except_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 729, __pyx_L5_except_error)
     __Pyx_GOTREF(__pyx_t_8);
     __pyx_t_9 = __Pyx_PyErr_GivenExceptionMatches(__pyx_t_5, __pyx_t_8);
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
@@ -9341,12 +8999,12 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
     __pyx_t_5 = 0; __pyx_t_6 = 0; __pyx_t_7 = 0;
     if (__pyx_t_9) {
       __Pyx_AddTraceback("pywrapfst._SymbolTable.find", __pyx_clineno, __pyx_lineno, __pyx_filename);
-      if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_6, &__pyx_t_5) < 0) __PYX_ERR(0, 739, __pyx_L5_except_error)
+      if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_6, &__pyx_t_5) < 0) __PYX_ERR(0, 729, __pyx_L5_except_error)
       __Pyx_GOTREF(__pyx_t_7);
       __Pyx_GOTREF(__pyx_t_6);
       __Pyx_GOTREF(__pyx_t_5);
 
-      /* "pywrapfst.pyx":740
+      /* "pywrapfst.pyx":730
  *       return self._table.FindIndex(tostring(key))
  *     except FstArgError:
  *       return self._table.FindSymbol(key)             # <<<<<<<<<<<<<<
@@ -9356,10 +9014,10 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
       __Pyx_XDECREF(__pyx_r);
       if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
         PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-        __PYX_ERR(0, 740, __pyx_L5_except_error)
+        __PYX_ERR(0, 730, __pyx_L5_except_error)
       }
-      __pyx_t_10 = __Pyx_PyInt_As_int64_t(__pyx_v_key); if (unlikely((__pyx_t_10 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 740, __pyx_L5_except_error)
-      __pyx_t_8 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_self->_table->Find(__pyx_t_10)); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 740, __pyx_L5_except_error)
+      __pyx_t_10 = __Pyx_PyInt_As_int64_t(__pyx_v_key); if (unlikely((__pyx_t_10 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 730, __pyx_L5_except_error)
+      __pyx_t_8 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_self->_table->Find(__pyx_t_10)); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 730, __pyx_L5_except_error)
       __Pyx_GOTREF(__pyx_t_8);
       __pyx_r = __pyx_t_8;
       __pyx_t_8 = 0;
@@ -9371,7 +9029,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
     goto __pyx_L5_except_error;
     __pyx_L5_except_error:;
 
-    /* "pywrapfst.pyx":737
+    /* "pywrapfst.pyx":727
  *           not found.
  *     """
  *     try:             # <<<<<<<<<<<<<<
@@ -9397,7 +9055,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
     goto __pyx_L0;
   }
 
-  /* "pywrapfst.pyx":720
+  /* "pywrapfst.pyx":710
  *     return _init_SymbolTable(self._table.Copy())
  * 
  *   def find(self, key):             # <<<<<<<<<<<<<<
@@ -9419,7 +9077,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":742
+/* "pywrapfst.pyx":732
  *       return self._table.FindSymbol(key)
  * 
  *   cpdef int64 get_nth_key(self, ssize_t pos) except *:             # <<<<<<<<<<<<<<
@@ -9427,7 +9085,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_10find(struct __pyx_obj_9pyw
  *     get_nth_key(self, pos)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_13get_nth_key(PyObject *__pyx_v_self, PyObject *__pyx_arg_pos); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_15get_nth_key(PyObject *__pyx_v_self, PyObject *__pyx_arg_pos); /*proto*/
 static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_12_SymbolTable_get_nth_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, Py_ssize_t __pyx_v_pos, int __pyx_skip_dispatch) {
   __pyx_t_10basictypes_int64 __pyx_r;
   __Pyx_RefNannyDeclarations
@@ -9436,89 +9094,74 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_12_SymbolTable_get_nth_key(
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  __pyx_t_10basictypes_int64 __pyx_t_7;
+  __pyx_t_10basictypes_int64 __pyx_t_6;
   __Pyx_RefNannySetupContext("get_nth_key", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_nth_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 742, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_13get_nth_key)) {
-      __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_pos); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 742, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_nth_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 732, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_15get_nth_key)) {
+        __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_pos); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 732, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 742, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 732, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 742, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 742, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 742, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 742, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_6 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_6 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 732, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_6;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_7 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_7 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 742, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_7;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":754
+  /* "pywrapfst.pyx":744
  *       The integer index of the n-th key, or NO_LABEL if not found.
  *     """
  *     return self._table.GetNthKey(pos)             # <<<<<<<<<<<<<<
  * 
- *   cpdef string labeled_checksum(self):
+ *   cpdef bytes labeled_checksum(self):
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 754, __pyx_L1_error)
+    __PYX_ERR(0, 744, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_table->GetNthKey(__pyx_v_pos);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":742
+  /* "pywrapfst.pyx":732
  *       return self._table.FindSymbol(key)
  * 
  *   cpdef int64 get_nth_key(self, ssize_t pos) except *:             # <<<<<<<<<<<<<<
@@ -9533,7 +9176,6 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_12_SymbolTable_get_nth_key(
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_AddTraceback("pywrapfst._SymbolTable.get_nth_key", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -9542,15 +9184,15 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_12_SymbolTable_get_nth_key(
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_13get_nth_key(PyObject *__pyx_v_self, PyObject *__pyx_arg_pos); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_12get_nth_key[] = "\n    get_nth_key(self, pos)\n\n    Retrieves the integer index of the n-th key in the table.\n\n    Args:\n      pos: The n-th key to retrieve.\n\n    Returns:\n      The integer index of the n-th key, or NO_LABEL if not found.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_13get_nth_key(PyObject *__pyx_v_self, PyObject *__pyx_arg_pos) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_15get_nth_key(PyObject *__pyx_v_self, PyObject *__pyx_arg_pos); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_14get_nth_key[] = "\n    get_nth_key(self, pos)\n\n    Retrieves the integer index of the n-th key in the table.\n\n    Args:\n      pos: The n-th key to retrieve.\n\n    Returns:\n      The integer index of the n-th key, or NO_LABEL if not found.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_15get_nth_key(PyObject *__pyx_v_self, PyObject *__pyx_arg_pos) {
   Py_ssize_t __pyx_v_pos;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("get_nth_key (wrapper)", 0);
   assert(__pyx_arg_pos); {
-    __pyx_v_pos = PyInt_AsSsize_t(__pyx_arg_pos); if (unlikely((__pyx_v_pos == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 742, __pyx_L3_error)
+    __pyx_v_pos = PyInt_AsSsize_t(__pyx_arg_pos); if (unlikely((__pyx_v_pos == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 732, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -9558,22 +9200,22 @@ static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_13get_nth_key(PyObject *__py
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_12get_nth_key(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((Py_ssize_t)__pyx_v_pos));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_14get_nth_key(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((Py_ssize_t)__pyx_v_pos));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_12get_nth_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, Py_ssize_t __pyx_v_pos) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_14get_nth_key(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, Py_ssize_t __pyx_v_pos) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   __pyx_t_10basictypes_int64 __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("get_nth_key", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_9pywrapfst_12_SymbolTable_get_nth_key(__pyx_v_self, __pyx_v_pos, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 742, __pyx_L1_error)
-  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 742, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_12_SymbolTable_get_nth_key(__pyx_v_self, __pyx_v_pos, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 732, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 732, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -9590,77 +9232,94 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_12get_nth_key(struct __pyx_o
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":756
+/* "pywrapfst.pyx":746
  *     return self._table.GetNthKey(pos)
  * 
- *   cpdef string labeled_checksum(self):             # <<<<<<<<<<<<<<
+ *   cpdef bytes labeled_checksum(self):             # <<<<<<<<<<<<<<
  *     """
  *     labeled_checksum(self)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_15labeled_checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static std::string __pyx_f_9pywrapfst_12_SymbolTable_labeled_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch) {
-  std::string __pyx_r;
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_17labeled_checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_f_9pywrapfst_12_SymbolTable_labeled_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch) {
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  std::string __pyx_t_5;
   __Pyx_RefNannySetupContext("labeled_checksum", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_labeled_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 756, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_15labeled_checksum)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_labeled_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 746, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_17labeled_checksum)) {
+        __Pyx_XDECREF(__pyx_r);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 746, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(PyBytes_CheckExact(__pyx_t_2))||((__pyx_t_2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_2)->tp_name), 0))) __PYX_ERR(0, 746, __pyx_L1_error)
+        __pyx_r = ((PyObject*)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 756, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 756, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 756, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":762
- *     Returns a string indicating the label-dependent MD5 checksum for the table.
+  /* "pywrapfst.pyx":752
+ *     Returns a bytestring indicating the label-dependent MD5 checksum.
  *     """
  *     return self._table.LabeledCheckSum()             # <<<<<<<<<<<<<<
  * 
  *   cpdef bool member(self, key):
  */
+  __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 762, __pyx_L1_error)
+    __PYX_ERR(0, 752, __pyx_L1_error)
   }
-  __pyx_r = __pyx_v_self->_table->LabeledCheckSum();
+  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_self->_table->LabeledCheckSum()); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 752, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":756
+  /* "pywrapfst.pyx":746
  *     return self._table.GetNthKey(pos)
  * 
- *   cpdef string labeled_checksum(self):             # <<<<<<<<<<<<<<
+ *   cpdef bytes labeled_checksum(self):             # <<<<<<<<<<<<<<
  *     """
  *     labeled_checksum(self)
  */
@@ -9671,34 +9330,35 @@ static std::string __pyx_f_9pywrapfst_12_SymbolTable_labeled_checksum(struct __p
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_WriteUnraisable("pywrapfst._SymbolTable.labeled_checksum", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
-  __Pyx_pretend_to_initialize(&__pyx_r);
+  __Pyx_AddTraceback("pywrapfst._SymbolTable.labeled_checksum", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
   __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_15labeled_checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_14labeled_checksum[] = "\n    labeled_checksum(self)\n\n    Returns a string indicating the label-dependent MD5 checksum for the table.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_15labeled_checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_17labeled_checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_16labeled_checksum[] = "\n    labeled_checksum(self)\n\n    Returns a bytestring indicating the label-dependent MD5 checksum.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_17labeled_checksum(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("labeled_checksum (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_14labeled_checksum(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_16labeled_checksum(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_14labeled_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_16labeled_checksum(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("labeled_checksum", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_12_SymbolTable_labeled_checksum(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 756, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_12_SymbolTable_labeled_checksum(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 746, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -9715,7 +9375,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_14labeled_checksum(struct __
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":764
+/* "pywrapfst.pyx":754
  *     return self._table.LabeledCheckSum()
  * 
  *   cpdef bool member(self, key):             # <<<<<<<<<<<<<<
@@ -9723,7 +9383,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_14labeled_checksum(struct __
  *     member(self, key)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_17member(PyObject *__pyx_v_self, PyObject *__pyx_v_key); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_19member(PyObject *__pyx_v_self, PyObject *__pyx_v_key); /*proto*/
 static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key, int __pyx_skip_dispatch) {
   bool __pyx_r;
   __Pyx_RefNannyDeclarations
@@ -9731,76 +9391,63 @@ static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  bool __pyx_t_6;
+  bool __pyx_t_5;
+  PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
   PyObject *__pyx_t_8 = NULL;
-  PyObject *__pyx_t_9 = NULL;
-  std::string __pyx_t_10;
-  int __pyx_t_11;
-  __pyx_t_10basictypes_int64 __pyx_t_12;
+  std::string __pyx_t_9;
+  int __pyx_t_10;
+  __pyx_t_10basictypes_int64 __pyx_t_11;
   __Pyx_RefNannySetupContext("member", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_member); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 764, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_17member)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_member); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 754, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_19member)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_key); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 764, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_key) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_key);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 754, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_key};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 764, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_key};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 764, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 764, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(__pyx_v_key);
-          __Pyx_GIVEREF(__pyx_v_key);
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_v_key);
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 764, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 754, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_6 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 764, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_6;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":780
+  /* "pywrapfst.pyx":770
  *       Whether or not the key is present (as a string or a index) in the table.
  *     """
  *     try:             # <<<<<<<<<<<<<<
@@ -9810,13 +9457,13 @@ static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst
   {
     __Pyx_PyThreadState_declare
     __Pyx_PyThreadState_assign
-    __Pyx_ExceptionSave(&__pyx_t_7, &__pyx_t_8, &__pyx_t_9);
+    __Pyx_ExceptionSave(&__pyx_t_6, &__pyx_t_7, &__pyx_t_8);
+    __Pyx_XGOTREF(__pyx_t_6);
     __Pyx_XGOTREF(__pyx_t_7);
     __Pyx_XGOTREF(__pyx_t_8);
-    __Pyx_XGOTREF(__pyx_t_9);
     /*try:*/ {
 
-      /* "pywrapfst.pyx":781
+      /* "pywrapfst.pyx":771
  *     """
  *     try:
  *       return self._table.MemberSymbol(tostring(key))             # <<<<<<<<<<<<<<
@@ -9825,13 +9472,13 @@ static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst
  */
       if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
         PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-        __PYX_ERR(0, 781, __pyx_L3_error)
+        __PYX_ERR(0, 771, __pyx_L3_error)
       }
-      __pyx_t_10 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 781, __pyx_L3_error)
-      __pyx_r = __pyx_v_self->_table->Member(__pyx_t_10);
+      __pyx_t_9 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 771, __pyx_L3_error)
+      __pyx_r = __pyx_v_self->_table->Member(__pyx_t_9);
       goto __pyx_L7_try_return;
 
-      /* "pywrapfst.pyx":780
+      /* "pywrapfst.pyx":770
  *       Whether or not the key is present (as a string or a index) in the table.
  *     """
  *     try:             # <<<<<<<<<<<<<<
@@ -9841,12 +9488,11 @@ static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst
     }
     __pyx_L3_error:;
     __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-    /* "pywrapfst.pyx":782
+    /* "pywrapfst.pyx":772
  *     try:
  *       return self._table.MemberSymbol(tostring(key))
  *     except FstArgError:             # <<<<<<<<<<<<<<
@@ -9854,20 +9500,20 @@ static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst
  * 
  */
     __Pyx_ErrFetch(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3);
-    __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 782, __pyx_L5_except_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_11 = __Pyx_PyErr_GivenExceptionMatches(__pyx_t_1, __pyx_t_5);
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 772, __pyx_L5_except_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_10 = __Pyx_PyErr_GivenExceptionMatches(__pyx_t_1, __pyx_t_4);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_ErrRestore(__pyx_t_1, __pyx_t_2, __pyx_t_3);
     __pyx_t_1 = 0; __pyx_t_2 = 0; __pyx_t_3 = 0;
-    if (__pyx_t_11) {
+    if (__pyx_t_10) {
       __Pyx_AddTraceback("pywrapfst._SymbolTable.member", __pyx_clineno, __pyx_lineno, __pyx_filename);
-      if (__Pyx_GetException(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1) < 0) __PYX_ERR(0, 782, __pyx_L5_except_error)
+      if (__Pyx_GetException(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1) < 0) __PYX_ERR(0, 772, __pyx_L5_except_error)
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_GOTREF(__pyx_t_2);
       __Pyx_GOTREF(__pyx_t_1);
 
-      /* "pywrapfst.pyx":783
+      /* "pywrapfst.pyx":773
  *       return self._table.MemberSymbol(tostring(key))
  *     except FstArgError:
  *       return self._table.MemberIndex(key)             # <<<<<<<<<<<<<<
@@ -9876,10 +9522,10 @@ static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst
  */
       if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
         PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-        __PYX_ERR(0, 783, __pyx_L5_except_error)
+        __PYX_ERR(0, 773, __pyx_L5_except_error)
       }
-      __pyx_t_12 = __Pyx_PyInt_As_int64_t(__pyx_v_key); if (unlikely((__pyx_t_12 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 783, __pyx_L5_except_error)
-      __pyx_r = __pyx_v_self->_table->Member(__pyx_t_12);
+      __pyx_t_11 = __Pyx_PyInt_As_int64_t(__pyx_v_key); if (unlikely((__pyx_t_11 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 773, __pyx_L5_except_error)
+      __pyx_r = __pyx_v_self->_table->Member(__pyx_t_11);
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -9888,33 +9534,33 @@ static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst
     goto __pyx_L5_except_error;
     __pyx_L5_except_error:;
 
-    /* "pywrapfst.pyx":780
+    /* "pywrapfst.pyx":770
  *       Whether or not the key is present (as a string or a index) in the table.
  *     """
  *     try:             # <<<<<<<<<<<<<<
  *       return self._table.MemberSymbol(tostring(key))
  *     except FstArgError:
  */
+    __Pyx_XGIVEREF(__pyx_t_6);
     __Pyx_XGIVEREF(__pyx_t_7);
     __Pyx_XGIVEREF(__pyx_t_8);
-    __Pyx_XGIVEREF(__pyx_t_9);
-    __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9);
+    __Pyx_ExceptionReset(__pyx_t_6, __pyx_t_7, __pyx_t_8);
     goto __pyx_L1_error;
     __pyx_L7_try_return:;
+    __Pyx_XGIVEREF(__pyx_t_6);
     __Pyx_XGIVEREF(__pyx_t_7);
     __Pyx_XGIVEREF(__pyx_t_8);
-    __Pyx_XGIVEREF(__pyx_t_9);
-    __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9);
+    __Pyx_ExceptionReset(__pyx_t_6, __pyx_t_7, __pyx_t_8);
     goto __pyx_L0;
     __pyx_L6_except_return:;
+    __Pyx_XGIVEREF(__pyx_t_6);
     __Pyx_XGIVEREF(__pyx_t_7);
     __Pyx_XGIVEREF(__pyx_t_8);
-    __Pyx_XGIVEREF(__pyx_t_9);
-    __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9);
+    __Pyx_ExceptionReset(__pyx_t_6, __pyx_t_7, __pyx_t_8);
     goto __pyx_L0;
   }
 
-  /* "pywrapfst.pyx":764
+  /* "pywrapfst.pyx":754
  *     return self._table.LabeledCheckSum()
  * 
  *   cpdef bool member(self, key):             # <<<<<<<<<<<<<<
@@ -9928,7 +9574,6 @@ static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_WriteUnraisable("pywrapfst._SymbolTable.member", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
   __pyx_r = 0;
   __pyx_L0:;
@@ -9937,26 +9582,26 @@ static bool __pyx_f_9pywrapfst_12_SymbolTable_member(struct __pyx_obj_9pywrapfst
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_17member(PyObject *__pyx_v_self, PyObject *__pyx_v_key); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_16member[] = "\n    member(self, key)\n\n    Given a symbol or index, returns whether it is found in the table.\n\n    This method returns a boolean indicating whether the given symbol or index\n    is present in the table. If one intends to perform subsequent lookup, it is\n    better to simply call the find method, catching the KeyError.\n\n    Args:\n      key: Either a string or an index.\n\n    Returns:\n      Whether or not the key is present (as a string or a index) in the table.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_17member(PyObject *__pyx_v_self, PyObject *__pyx_v_key) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_19member(PyObject *__pyx_v_self, PyObject *__pyx_v_key); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_18member[] = "\n    member(self, key)\n\n    Given a symbol or index, returns whether it is found in the table.\n\n    This method returns a boolean indicating whether the given symbol or index\n    is present in the table. If one intends to perform subsequent lookup, it is\n    better to simply call the find method, catching the KeyError.\n\n    Args:\n      key: Either a string or an index.\n\n    Returns:\n      Whether or not the key is present (as a string or a index) in the table.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_19member(PyObject *__pyx_v_self, PyObject *__pyx_v_key) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("member (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_16member(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_key));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_18member(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_key));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_16member(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_18member(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("member", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_12_SymbolTable_member(__pyx_v_self, __pyx_v_key, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 764, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_12_SymbolTable_member(__pyx_v_self, __pyx_v_key, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 754, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -9973,7 +9618,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_16member(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":785
+/* "pywrapfst.pyx":775
  *       return self._table.MemberIndex(key)
  * 
  *   def __contains__(self, key):             # <<<<<<<<<<<<<<
@@ -9982,24 +9627,24 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_16member(struct __pyx_obj_9p
  */
 
 /* Python wrapper */
-static int __pyx_pw_9pywrapfst_12_SymbolTable_19__contains__(PyObject *__pyx_v_self, PyObject *__pyx_v_key); /*proto*/
-static int __pyx_pw_9pywrapfst_12_SymbolTable_19__contains__(PyObject *__pyx_v_self, PyObject *__pyx_v_key) {
+static int __pyx_pw_9pywrapfst_12_SymbolTable_21__contains__(PyObject *__pyx_v_self, PyObject *__pyx_v_key); /*proto*/
+static int __pyx_pw_9pywrapfst_12_SymbolTable_21__contains__(PyObject *__pyx_v_self, PyObject *__pyx_v_key) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__contains__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_18__contains__(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_key));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_20__contains__(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_key));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9pywrapfst_12_SymbolTable_18__contains__(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key) {
+static int __pyx_pf_9pywrapfst_12_SymbolTable_20__contains__(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_key) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__contains__", 0);
 
-  /* "pywrapfst.pyx":786
+  /* "pywrapfst.pyx":776
  * 
  *   def __contains__(self, key):
  *     return self.member(key)             # <<<<<<<<<<<<<<
@@ -10008,12 +9653,12 @@ static int __pyx_pf_9pywrapfst_12_SymbolTable_18__contains__(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "member");
-    __PYX_ERR(0, 786, __pyx_L1_error)
+    __PYX_ERR(0, 776, __pyx_L1_error)
   }
   __pyx_r = ((struct __pyx_vtabstruct_9pywrapfst__SymbolTable *)__pyx_v_self->__pyx_vtab)->member(__pyx_v_self, __pyx_v_key, 0);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":785
+  /* "pywrapfst.pyx":775
  *       return self._table.MemberIndex(key)
  * 
  *   def __contains__(self, key):             # <<<<<<<<<<<<<<
@@ -10030,7 +9675,7 @@ static int __pyx_pf_9pywrapfst_12_SymbolTable_18__contains__(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":788
+/* "pywrapfst.pyx":778
  *     return self.member(key)
  * 
  *   cpdef string name(self):             # <<<<<<<<<<<<<<
@@ -10038,7 +9683,7 @@ static int __pyx_pf_9pywrapfst_12_SymbolTable_18__contains__(struct __pyx_obj_9p
  *     name(self)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_21name(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_23name(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
 static std::string __pyx_f_9pywrapfst_12_SymbolTable_name(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch) {
   std::string __pyx_r;
   __Pyx_RefNannyDeclarations
@@ -10051,39 +9696,52 @@ static std::string __pyx_f_9pywrapfst_12_SymbolTable_name(struct __pyx_obj_9pywr
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_name_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 788, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_21name)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_name_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 778, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_23name)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 778, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 778, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 788, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 788, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 788, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":794
+  /* "pywrapfst.pyx":784
  *     Returns the symbol table's name.
  *     """
  *     return self._table.Name()             # <<<<<<<<<<<<<<
@@ -10092,12 +9750,12 @@ static std::string __pyx_f_9pywrapfst_12_SymbolTable_name(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 794, __pyx_L1_error)
+    __PYX_ERR(0, 784, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_table->Name();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":788
+  /* "pywrapfst.pyx":778
  *     return self.member(key)
  * 
  *   cpdef string name(self):             # <<<<<<<<<<<<<<
@@ -10119,26 +9777,26 @@ static std::string __pyx_f_9pywrapfst_12_SymbolTable_name(struct __pyx_obj_9pywr
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_21name(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_20name[] = "\n    name(self)\n\n    Returns the symbol table's name.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_21name(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_23name(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_22name[] = "\n    name(self)\n\n    Returns the symbol table's name.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_23name(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("name (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_20name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_22name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_20name(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_22name(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("name", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_12_SymbolTable_name(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 788, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_12_SymbolTable_name(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 778, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -10155,7 +9813,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_20name(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":796
+/* "pywrapfst.pyx":786
  *     return self._table.Name()
  * 
  *   cpdef size_t num_symbols(self):             # <<<<<<<<<<<<<<
@@ -10163,7 +9821,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_20name(struct __pyx_obj_9pyw
  *     num_symbols(self)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_23num_symbols(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_25num_symbols(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
 static size_t __pyx_f_9pywrapfst_12_SymbolTable_num_symbols(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch) {
   size_t __pyx_r;
   __Pyx_RefNannyDeclarations
@@ -10176,39 +9834,52 @@ static size_t __pyx_f_9pywrapfst_12_SymbolTable_num_symbols(struct __pyx_obj_9py
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 796, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_23num_symbols)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 786, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_25num_symbols)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 786, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_5 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 786, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 796, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 796, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_5 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 796, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":802
+  /* "pywrapfst.pyx":792
  *     Returns the number of symbols in the symbol table.
  *     """
  *     return self._table.NumSymbols()             # <<<<<<<<<<<<<<
@@ -10217,12 +9888,12 @@ static size_t __pyx_f_9pywrapfst_12_SymbolTable_num_symbols(struct __pyx_obj_9py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 802, __pyx_L1_error)
+    __PYX_ERR(0, 792, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_table->NumSymbols();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":796
+  /* "pywrapfst.pyx":786
  *     return self._table.Name()
  * 
  *   cpdef size_t num_symbols(self):             # <<<<<<<<<<<<<<
@@ -10244,26 +9915,26 @@ static size_t __pyx_f_9pywrapfst_12_SymbolTable_num_symbols(struct __pyx_obj_9py
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_23num_symbols(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_22num_symbols[] = "\n    num_symbols(self)\n\n    Returns the number of symbols in the symbol table.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_23num_symbols(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_25num_symbols(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_24num_symbols[] = "\n    num_symbols(self)\n\n    Returns the number of symbols in the symbol table.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_25num_symbols(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("num_symbols (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_22num_symbols(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_24num_symbols(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_22num_symbols(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_24num_symbols(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("num_symbols", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_FromSize_t(__pyx_f_9pywrapfst_12_SymbolTable_num_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 796, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_FromSize_t(__pyx_f_9pywrapfst_12_SymbolTable_num_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 786, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -10280,7 +9951,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_22num_symbols(struct __pyx_o
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":804
+/* "pywrapfst.pyx":794
  *     return self._table.NumSymbols()
  * 
  *   cpdef void write(self, filename) except *:             # <<<<<<<<<<<<<<
@@ -10288,77 +9959,64 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_22num_symbols(struct __pyx_o
  *     write(self, filename)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_25write(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_27write(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
 static void __pyx_f_9pywrapfst_12_SymbolTable_write(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename, int __pyx_skip_dispatch) {
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  std::string __pyx_t_6;
-  int __pyx_t_7;
-  PyObject *__pyx_t_8 = NULL;
+  std::string __pyx_t_5;
+  int __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("write", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 804, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_25write)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 794, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_27write)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_filename); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 804, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_filename);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 794, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 804, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 804, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 804, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(__pyx_v_filename);
-          __Pyx_GIVEREF(__pyx_v_filename);
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_v_filename);
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 804, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":818
+  /* "pywrapfst.pyx":808
  *       FstIOError: Write failed.
  *     """
  *     if not self._table.Write(tostring(filename)):             # <<<<<<<<<<<<<<
@@ -10367,117 +10025,59 @@ static void __pyx_f_9pywrapfst_12_SymbolTable_write(struct __pyx_obj_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 818, __pyx_L1_error)
+    __PYX_ERR(0, 808, __pyx_L1_error)
   }
-  __pyx_t_6 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 818, __pyx_L1_error)
-  __pyx_t_7 = ((!(__pyx_v_self->_table->Write(__pyx_t_6) != 0)) != 0);
-  if (unlikely(__pyx_t_7)) {
+  __pyx_t_5 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 808, __pyx_L1_error)
+  __pyx_t_6 = ((!(__pyx_v_self->_table->Write(__pyx_t_5) != 0)) != 0);
+  if (unlikely(__pyx_t_6)) {
 
-    /* "pywrapfst.pyx":819
+    /* "pywrapfst.pyx":809
  *     """
  *     if not self._table.Write(tostring(filename)):
  *       raise FstIOError("Write failed: {!r}".format(filename))             # <<<<<<<<<<<<<<
  * 
  *   cpdef void write_text(self, filename) except *:
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 819, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 809, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Write_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 819, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_4 = NULL;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
-      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5);
-      if (likely(__pyx_t_4)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-        __Pyx_INCREF(__pyx_t_4);
+    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Write_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 809, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_7 = NULL;
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_7)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_7);
         __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_5, function);
-      }
-    }
-    if (!__pyx_t_4) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_filename); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 819, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 819, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 819, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 819, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_4); __pyx_t_4 = NULL;
-        __Pyx_INCREF(__pyx_v_filename);
-        __Pyx_GIVEREF(__pyx_v_filename);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_filename);
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 819, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+        __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = NULL;
+    __pyx_t_3 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_7, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_filename);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 809, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __pyx_t_4 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_5)) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_4)) {
         PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_4);
         __Pyx_INCREF(function);
         __Pyx_DECREF_SET(__pyx_t_2, function);
       }
     }
-    if (!__pyx_t_5) {
-      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 819, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-        __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 819, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-        __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 819, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 819, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_3);
-        __pyx_t_3 = 0;
-        __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 819, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 809, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_Raise(__pyx_t_1, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 819, __pyx_L1_error)
+    __PYX_ERR(0, 809, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":818
+    /* "pywrapfst.pyx":808
  *       FstIOError: Write failed.
  *     """
  *     if not self._table.Write(tostring(filename)):             # <<<<<<<<<<<<<<
@@ -10486,7 +10086,7 @@ static void __pyx_f_9pywrapfst_12_SymbolTable_write(struct __pyx_obj_9pywrapfst_
  */
   }
 
-  /* "pywrapfst.pyx":804
+  /* "pywrapfst.pyx":794
  *     return self._table.NumSymbols()
  * 
  *   cpdef void write(self, filename) except *:             # <<<<<<<<<<<<<<
@@ -10501,35 +10101,34 @@ static void __pyx_f_9pywrapfst_12_SymbolTable_write(struct __pyx_obj_9pywrapfst_
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_AddTraceback("pywrapfst._SymbolTable.write", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_25write(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_24write[] = "\n    write(self, filename)\n\n    Serializes symbol table to a file.\n\n    This methods writes the SymbolTable to a file in binary format.\n\n    Args:\n      filename: The string location of the output file.\n\n    Raises:\n      FstIOError: Write failed.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_25write(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_27write(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_26write[] = "\n    write(self, filename)\n\n    Serializes symbol table to a file.\n\n    This methods writes the SymbolTable to a file in binary format.\n\n    Args:\n      filename: The string location of the output file.\n\n    Raises:\n      FstIOError: Write failed.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_27write(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_24write(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_filename));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_26write(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_filename));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_24write(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_26write(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("write", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_f_9pywrapfst_12_SymbolTable_write(__pyx_v_self, __pyx_v_filename, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 804, __pyx_L1_error)
-  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 804, __pyx_L1_error)
+  __pyx_f_9pywrapfst_12_SymbolTable_write(__pyx_v_self, __pyx_v_filename, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 794, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 794, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -10546,7 +10145,7 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_24write(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":821
+/* "pywrapfst.pyx":811
  *       raise FstIOError("Write failed: {!r}".format(filename))
  * 
  *   cpdef void write_text(self, filename) except *:             # <<<<<<<<<<<<<<
@@ -10554,77 +10153,64 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_24write(struct __pyx_obj_9py
  *     write_text(self, filename)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_27write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_29write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
 static void __pyx_f_9pywrapfst_12_SymbolTable_write_text(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename, int __pyx_skip_dispatch) {
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  std::string __pyx_t_6;
-  int __pyx_t_7;
-  PyObject *__pyx_t_8 = NULL;
+  std::string __pyx_t_5;
+  int __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("write_text", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write_text); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 821, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_27write_text)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write_text); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 811, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_29write_text)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_filename); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 821, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_filename);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 811, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 821, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 821, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 821, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(__pyx_v_filename);
-          __Pyx_GIVEREF(__pyx_v_filename);
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_v_filename);
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 821, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":835
+  /* "pywrapfst.pyx":825
  *       FstIOError: Write failed.
  *     """
  *     if not self._table.WriteText(tostring(filename)):             # <<<<<<<<<<<<<<
@@ -10633,117 +10219,59 @@ static void __pyx_f_9pywrapfst_12_SymbolTable_write_text(struct __pyx_obj_9pywra
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 835, __pyx_L1_error)
+    __PYX_ERR(0, 825, __pyx_L1_error)
   }
-  __pyx_t_6 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 835, __pyx_L1_error)
-  __pyx_t_7 = ((!(__pyx_v_self->_table->WriteText(__pyx_t_6) != 0)) != 0);
-  if (unlikely(__pyx_t_7)) {
+  __pyx_t_5 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 825, __pyx_L1_error)
+  __pyx_t_6 = ((!(__pyx_v_self->_table->WriteText(__pyx_t_5) != 0)) != 0);
+  if (unlikely(__pyx_t_6)) {
 
-    /* "pywrapfst.pyx":836
+    /* "pywrapfst.pyx":826
  *     """
  *     if not self._table.WriteText(tostring(filename)):
  *       raise FstIOError("Write failed: {!r}".format(filename))             # <<<<<<<<<<<<<<
  * 
- * 
+ *   cpdef bytes write_to_string(self):
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 836, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 826, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Write_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 836, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_4 = NULL;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
-      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5);
-      if (likely(__pyx_t_4)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-        __Pyx_INCREF(__pyx_t_4);
+    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Write_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 826, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_7 = NULL;
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_7)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_7);
         __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_5, function);
-      }
-    }
-    if (!__pyx_t_4) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_filename); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 836, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 836, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 836, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 836, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_4); __pyx_t_4 = NULL;
-        __Pyx_INCREF(__pyx_v_filename);
-        __Pyx_GIVEREF(__pyx_v_filename);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_filename);
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 836, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+        __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = NULL;
+    __pyx_t_3 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_7, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_filename);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 826, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __pyx_t_4 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_5)) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_4)) {
         PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_4);
         __Pyx_INCREF(function);
         __Pyx_DECREF_SET(__pyx_t_2, function);
       }
     }
-    if (!__pyx_t_5) {
-      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 836, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-        __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 836, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-        __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 836, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 836, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_3);
-        __pyx_t_3 = 0;
-        __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 836, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 826, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_Raise(__pyx_t_1, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 836, __pyx_L1_error)
+    __PYX_ERR(0, 826, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":835
+    /* "pywrapfst.pyx":825
  *       FstIOError: Write failed.
  *     """
  *     if not self._table.WriteText(tostring(filename)):             # <<<<<<<<<<<<<<
@@ -10752,7 +10280,7 @@ static void __pyx_f_9pywrapfst_12_SymbolTable_write_text(struct __pyx_obj_9pywra
  */
   }
 
-  /* "pywrapfst.pyx":821
+  /* "pywrapfst.pyx":811
  *       raise FstIOError("Write failed: {!r}".format(filename))
  * 
  *   cpdef void write_text(self, filename) except *:             # <<<<<<<<<<<<<<
@@ -10767,35 +10295,34 @@ static void __pyx_f_9pywrapfst_12_SymbolTable_write_text(struct __pyx_obj_9pywra
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_AddTraceback("pywrapfst._SymbolTable.write_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_27write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
-static char __pyx_doc_9pywrapfst_12_SymbolTable_26write_text[] = "\n    write_text(self, filename)\n\n    Writes symbol table to text file.\n\n    This method writes the SymbolTable to a file in human-readable format.\n\n    Args:\n      filename: The string location of the output file.\n\n    Raises:\n      FstIOError: Write failed.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_27write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_29write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_28write_text[] = "\n    write_text(self, filename)\n\n    Writes symbol table to text file.\n\n    This method writes the SymbolTable to a file in human-readable format.\n\n    Args:\n      filename: The string location of the output file.\n\n    Raises:\n      FstIOError: Write failed.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_29write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_text (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_26write_text(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_filename));
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_28write_text(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v_filename));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_26write_text(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_28write_text(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("write_text", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_f_9pywrapfst_12_SymbolTable_write_text(__pyx_v_self, __pyx_v_filename, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 821, __pyx_L1_error)
-  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 821, __pyx_L1_error)
+  __pyx_f_9pywrapfst_12_SymbolTable_write_text(__pyx_v_self, __pyx_v_filename, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 811, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 811, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -10812,114 +10339,199 @@ static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_26write_text(struct __pyx_ob
   return __pyx_r;
 }
 
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
+/* "pywrapfst.pyx":828
+ *       raise FstIOError("Write failed: {!r}".format(filename))
+ * 
+ *   cpdef bytes write_to_string(self):             # <<<<<<<<<<<<<<
+ *     """
+ *     write_to_string(self)
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_29__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_29__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_28__reduce_cython__(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_28__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_31write_to_string(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_f_9pywrapfst_12_SymbolTable_write_to_string(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, int __pyx_skip_dispatch) {
+  std::stringstream __pyx_v_sstrm;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_t_5;
+  __Pyx_RefNannySetupContext("write_to_string", 0);
+  /* Check if called by wrapper */
+  if (unlikely(__pyx_skip_dispatch)) ;
+  /* Check if overridden in Python */
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write_to_string); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 828, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12_SymbolTable_31write_to_string)) {
+        __Pyx_XDECREF(__pyx_r);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
+        }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 828, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(PyBytes_CheckExact(__pyx_t_2))||((__pyx_t_2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_2)->tp_name), 0))) __PYX_ERR(0, 828, __pyx_L1_error)
+        __pyx_r = ((PyObject*)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    }
+    #endif
+  }
 
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
+  /* "pywrapfst.pyx":843
+ *     """
+ *     cdef stringstream sstrm
+ *     if not self._table.Write(sstrm):             # <<<<<<<<<<<<<<
+ *       raise FstIOError("Write to string failed")
+ *     return sstrm.str()
+ */
+  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
+    __PYX_ERR(0, 843, __pyx_L1_error)
+  }
+  __pyx_t_5 = ((!(__pyx_v_self->_table->Write(__pyx_v_sstrm) != 0)) != 0);
+  if (unlikely(__pyx_t_5)) {
+
+    /* "pywrapfst.pyx":844
+ *     cdef stringstream sstrm
+ *     if not self._table.Write(sstrm):
+ *       raise FstIOError("Write to string failed")             # <<<<<<<<<<<<<<
+ *     return sstrm.str()
+ * 
+ */
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 844, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_3 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_3)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_kp_u_Write_to_string_failed) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_kp_u_Write_to_string_failed);
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 844, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 844, __pyx_L1_error)
+
+    /* "pywrapfst.pyx":843
+ *     """
+ *     cdef stringstream sstrm
+ *     if not self._table.Write(sstrm):             # <<<<<<<<<<<<<<
+ *       raise FstIOError("Write to string failed")
+ *     return sstrm.str()
+ */
+  }
+
+  /* "pywrapfst.pyx":845
+ *     if not self._table.Write(sstrm):
+ *       raise FstIOError("Write to string failed")
+ *     return sstrm.str()             # <<<<<<<<<<<<<<
+ * 
+ * 
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_sstrm.str()); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 845, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_r = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
 
-  /* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
+  /* "pywrapfst.pyx":828
+ *       raise FstIOError("Write failed: {!r}".format(filename))
+ * 
+ *   cpdef bytes write_to_string(self):             # <<<<<<<<<<<<<<
+ *     """
+ *     write_to_string(self)
  */
 
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._SymbolTable.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("pywrapfst._SymbolTable.write_to_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- */
-
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_31__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_31__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_31write_to_string(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9pywrapfst_12_SymbolTable_30write_to_string[] = "\n    write_to_string(self)\n\n    Serializes SymbolTable to a string.\n\n    Returns:\n      A bytestring.\n\n    Raises:\n      FstIOError: Write to string failed.\n\n    See also: `read_from_string`.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_12_SymbolTable_31write_to_string(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_30__setstate_cython__(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
+  __Pyx_RefNannySetupContext("write_to_string (wrapper)", 0);
+  __pyx_r = __pyx_pf_9pywrapfst_12_SymbolTable_30write_to_string(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_30__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pf_9pywrapfst_12_SymbolTable_30write_to_string(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_RefNannySetupContext("write_to_string", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __pyx_f_9pywrapfst_12_SymbolTable_write_to_string(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 828, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 4, __pyx_L1_error)
-
-  /* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- */
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
 
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._SymbolTable.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("pywrapfst._SymbolTable.write_to_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":854
+/* "pywrapfst.pyx":863
  *   # Doing so will allow undefined behavior.
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -10952,7 +10564,7 @@ static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable___repr__(struct
   PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":855
+  /* "pywrapfst.pyx":864
  * 
  *   def __repr__(self):
  *     return "<const EncodeMapper SymbolTable {!r} at 0x{:x}>".format(self.name(),             # <<<<<<<<<<<<<<
@@ -10960,23 +10572,23 @@ static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable___repr__(struct
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_const_EncodeMapper_SymbolTable, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 855, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_const_EncodeMapper_SymbolTable, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 864, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "name");
-    __PYX_ERR(0, 855, __pyx_L1_error)
+    __PYX_ERR(0, 864, __pyx_L1_error)
   }
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__EncodeMapperSymbolTable *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 855, __pyx_L1_error)
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__EncodeMapperSymbolTable *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 864, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
 
-  /* "pywrapfst.pyx":856
+  /* "pywrapfst.pyx":865
  *   def __repr__(self):
  *     return "<const EncodeMapper SymbolTable {!r} at 0x{:x}>".format(self.name(),
  *                                                                     id(self))             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 856, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 865, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_t_5 = NULL;
   __pyx_t_6 = 0;
@@ -10993,7 +10605,7 @@ static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable___repr__(struct
   #if CYTHON_FAST_PYCALL
   if (PyFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 855, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 864, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -11003,7 +10615,7 @@ static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable___repr__(struct
   #if CYTHON_FAST_PYCCALL
   if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 855, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 864, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -11011,7 +10623,7 @@ static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable___repr__(struct
   } else
   #endif
   {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 855, __pyx_L1_error)
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 864, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_7);
     if (__pyx_t_5) {
       __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
@@ -11022,7 +10634,7 @@ static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable___repr__(struct
     PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_4);
     __pyx_t_3 = 0;
     __pyx_t_4 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 855, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 864, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   }
@@ -11031,7 +10643,7 @@ static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable___repr__(struct
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":854
+  /* "pywrapfst.pyx":863
  *   # Doing so will allow undefined behavior.
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -11055,114 +10667,7 @@ static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable___repr__(struct
   return __pyx_r;
 }
 
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_24_EncodeMapperSymbolTable_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_24_EncodeMapperSymbolTable_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable_2__reduce_cython__(((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable_2__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__9, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 2, __pyx_L1_error)
-
-  /* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._EncodeMapperSymbolTable.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_24_EncodeMapperSymbolTable_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_24_EncodeMapperSymbolTable_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable_4__setstate_cython__(((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_24_EncodeMapperSymbolTable_4__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__10, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 4, __pyx_L1_error)
-
-  /* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._EncodeMapperSymbolTable.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "pywrapfst.pyx":873
+/* "pywrapfst.pyx":882
  *   # Doing so will allow undefined behavior.
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -11195,7 +10700,7 @@ static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable___repr__(struct __pyx_obj
   PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":874
+  /* "pywrapfst.pyx":883
  * 
  *   def __repr__(self):
  *     return "<const Fst SymbolTable {!r} at 0x{:x}>".format(self.name(),             # <<<<<<<<<<<<<<
@@ -11203,23 +10708,23 @@ static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable___repr__(struct __pyx_obj
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_const_Fst_SymbolTable_r_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 874, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_const_Fst_SymbolTable_r_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 883, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "name");
-    __PYX_ERR(0, 874, __pyx_L1_error)
+    __PYX_ERR(0, 883, __pyx_L1_error)
   }
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__FstSymbolTable *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 874, __pyx_L1_error)
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__FstSymbolTable *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 883, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
 
-  /* "pywrapfst.pyx":875
+  /* "pywrapfst.pyx":884
  *   def __repr__(self):
  *     return "<const Fst SymbolTable {!r} at 0x{:x}>".format(self.name(),
  *                                                            id(self))             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 875, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 884, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_t_5 = NULL;
   __pyx_t_6 = 0;
@@ -11236,7 +10741,7 @@ static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable___repr__(struct __pyx_obj
   #if CYTHON_FAST_PYCALL
   if (PyFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 874, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 883, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -11246,7 +10751,7 @@ static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable___repr__(struct __pyx_obj
   #if CYTHON_FAST_PYCCALL
   if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 874, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 883, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -11254,7 +10759,7 @@ static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable___repr__(struct __pyx_obj
   } else
   #endif
   {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 874, __pyx_L1_error)
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 883, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_7);
     if (__pyx_t_5) {
       __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
@@ -11265,7 +10770,7 @@ static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable___repr__(struct __pyx_obj
     PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_4);
     __pyx_t_3 = 0;
     __pyx_t_4 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 874, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 883, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   }
@@ -11274,7 +10779,7 @@ static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable___repr__(struct __pyx_obj
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":873
+  /* "pywrapfst.pyx":882
  *   # Doing so will allow undefined behavior.
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -11298,124 +10803,17 @@ static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable___repr__(struct __pyx_obj
   return __pyx_r;
 }
 
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_15_FstSymbolTable_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_15_FstSymbolTable_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_15_FstSymbolTable_2__reduce_cython__(((struct __pyx_obj_9pywrapfst__FstSymbolTable *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable_2__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 2, __pyx_L1_error)
-
-  /* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._FstSymbolTable.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_15_FstSymbolTable_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_15_FstSymbolTable_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_15_FstSymbolTable_4__setstate_cython__(((struct __pyx_obj_9pywrapfst__FstSymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_15_FstSymbolTable_4__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__12, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 4, __pyx_L1_error)
-
-  /* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._FstSymbolTable.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "pywrapfst.pyx":889
+/* "pywrapfst.pyx":898
  *   """
  * 
- *   cpdef int64 add_symbol(self, symbol, int64 key=kNoSymbol):             # <<<<<<<<<<<<<<
+ *   cpdef int64 add_symbol(self, symbol, int64 key=fst.kNoSymbol):             # <<<<<<<<<<<<<<
  *     """
  *     add_symbol(self, symbol, key=NO_SYMBOL)
  */
 
 static PyObject *__pyx_pw_9pywrapfst_19_MutableSymbolTable_1add_symbol(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_19_MutableSymbolTable_add_symbol(struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self, PyObject *__pyx_v_symbol, int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_19_MutableSymbolTable_add_symbol *__pyx_optional_args) {
-  __pyx_t_10basictypes_int64 __pyx_v_key = __pyx_k__13;
+  __pyx_t_10basictypes_int64 __pyx_v_key = __pyx_k__3;
   std::string __pyx_v_symbol_string;
   __pyx_t_10basictypes_int64 __pyx_r;
   __Pyx_RefNannyDeclarations
@@ -11438,121 +10836,129 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_19_MutableSymbolTable_add_s
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_add_symbol); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 889, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_19_MutableSymbolTable_1add_symbol)) {
-      __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 889, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      __pyx_t_6 = 0;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
-          __pyx_t_6 = 1;
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_add_symbol); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 898, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_19_MutableSymbolTable_1add_symbol)) {
+        __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 898, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        __pyx_t_6 = 0;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+            __pyx_t_6 = 1;
+          }
+        }
+        #if CYTHON_FAST_PYCALL
+        if (PyFunction_Check(__pyx_t_4)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_symbol, __pyx_t_3};
+          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 898, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        } else
+        #endif
+        #if CYTHON_FAST_PYCCALL
+        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_symbol, __pyx_t_3};
+          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 898, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        } else
+        #endif
+        {
+          __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 898, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_7);
+          if (__pyx_t_5) {
+            __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
+          }
+          __Pyx_INCREF(__pyx_v_symbol);
+          __Pyx_GIVEREF(__pyx_v_symbol);
+          PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_v_symbol);
+          __Pyx_GIVEREF(__pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_3);
+          __pyx_t_3 = 0;
+          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 898, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
         }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_8 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_8 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 898, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_8;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_symbol, __pyx_t_3};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 889, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_symbol, __pyx_t_3};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 889, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
       #endif
-      {
-        __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 889, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        if (__pyx_t_5) {
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        }
-        __Pyx_INCREF(__pyx_v_symbol);
-        __Pyx_GIVEREF(__pyx_v_symbol);
-        PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_v_symbol);
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_3);
-        __pyx_t_3 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 889, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_8 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_8 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 889, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_8;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":906
+  /* "pywrapfst.pyx":915
  *       The integer key of the new symbol.
  *     """
  *     cdef string symbol_string = tostring(symbol)             # <<<<<<<<<<<<<<
- *     if key != kNoSymbol:
+ *     if key != fst.kNoSymbol:
  *       return self._table.AddSymbol(symbol_string, key)
  */
-  __pyx_t_9 = __pyx_f_9pywrapfst_tostring(__pyx_v_symbol, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 906, __pyx_L1_error)
+  __pyx_t_9 = __pyx_f_9pywrapfst_tostring(__pyx_v_symbol, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 915, __pyx_L1_error)
   __pyx_v_symbol_string = __pyx_t_9;
 
-  /* "pywrapfst.pyx":907
+  /* "pywrapfst.pyx":916
  *     """
  *     cdef string symbol_string = tostring(symbol)
- *     if key != kNoSymbol:             # <<<<<<<<<<<<<<
+ *     if key != fst.kNoSymbol:             # <<<<<<<<<<<<<<
  *       return self._table.AddSymbol(symbol_string, key)
  *     else:
  */
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_v_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 907, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_kNoSymbol); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 907, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_4 = PyObject_RichCompare(__pyx_t_1, __pyx_t_2, Py_NE); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 907, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_10 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_10 < 0)) __PYX_ERR(0, 907, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_10 = ((__pyx_v_key != fst::kNoSymbol) != 0);
   if (__pyx_t_10) {
 
-    /* "pywrapfst.pyx":908
+    /* "pywrapfst.pyx":917
  *     cdef string symbol_string = tostring(symbol)
- *     if key != kNoSymbol:
+ *     if key != fst.kNoSymbol:
  *       return self._table.AddSymbol(symbol_string, key)             # <<<<<<<<<<<<<<
  *     else:
  *       return self._table.AddSymbol(symbol_string)
  */
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 908, __pyx_L1_error)
+      __PYX_ERR(0, 917, __pyx_L1_error)
     }
     __pyx_r = __pyx_v_self->__pyx_base._table->AddSymbol(__pyx_v_symbol_string, __pyx_v_key);
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":907
+    /* "pywrapfst.pyx":916
  *     """
  *     cdef string symbol_string = tostring(symbol)
- *     if key != kNoSymbol:             # <<<<<<<<<<<<<<
+ *     if key != fst.kNoSymbol:             # <<<<<<<<<<<<<<
  *       return self._table.AddSymbol(symbol_string, key)
  *     else:
  */
   }
 
-  /* "pywrapfst.pyx":910
+  /* "pywrapfst.pyx":919
  *       return self._table.AddSymbol(symbol_string, key)
  *     else:
  *       return self._table.AddSymbol(symbol_string)             # <<<<<<<<<<<<<<
@@ -11562,16 +10968,16 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_19_MutableSymbolTable_add_s
   /*else*/ {
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 910, __pyx_L1_error)
+      __PYX_ERR(0, 919, __pyx_L1_error)
     }
     __pyx_r = __pyx_v_self->__pyx_base._table->AddSymbol(__pyx_v_symbol_string);
     goto __pyx_L0;
   }
 
-  /* "pywrapfst.pyx":889
+  /* "pywrapfst.pyx":898
  *   """
  * 
- *   cpdef int64 add_symbol(self, symbol, int64 key=kNoSymbol):             # <<<<<<<<<<<<<<
+ *   cpdef int64 add_symbol(self, symbol, int64 key=fst.kNoSymbol):             # <<<<<<<<<<<<<<
  *     """
  *     add_symbol(self, symbol, key=NO_SYMBOL)
  */
@@ -11627,7 +11033,7 @@ static PyObject *__pyx_pw_9pywrapfst_19_MutableSymbolTable_1add_symbol(PyObject
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "add_symbol") < 0)) __PYX_ERR(0, 889, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "add_symbol") < 0)) __PYX_ERR(0, 898, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -11640,14 +11046,14 @@ static PyObject *__pyx_pw_9pywrapfst_19_MutableSymbolTable_1add_symbol(PyObject
     }
     __pyx_v_symbol = values[0];
     if (values[1]) {
-      __pyx_v_key = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_key == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 889, __pyx_L3_error)
+      __pyx_v_key = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_key == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 898, __pyx_L3_error)
     } else {
-      __pyx_v_key = __pyx_k__13;
+      __pyx_v_key = __pyx_k__3;
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("add_symbol", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 889, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("add_symbol", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 898, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableSymbolTable.add_symbol", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -11671,7 +11077,7 @@ static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_add_symbol(struct __p
   __pyx_t_2.__pyx_n = 1;
   __pyx_t_2.key = __pyx_v_key;
   __pyx_t_1 = __pyx_vtabptr_9pywrapfst__MutableSymbolTable->add_symbol(__pyx_v_self, __pyx_v_symbol, 1, &__pyx_t_2); 
-  __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 889, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 898, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
@@ -11688,7 +11094,7 @@ static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_add_symbol(struct __p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":912
+/* "pywrapfst.pyx":921
  *       return self._table.AddSymbol(symbol_string)
  * 
  *   cpdef void add_table(self, _SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -11703,67 +11109,54 @@ static void __pyx_f_9pywrapfst_19_MutableSymbolTable_add_table(struct __pyx_obj_
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("add_table", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_add_table); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 912, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_19_MutableSymbolTable_3add_table)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_add_table); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 921, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_19_MutableSymbolTable_3add_table)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_syms)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 912, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, ((PyObject *)__pyx_v_syms)) : __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_syms));
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 921, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_syms)};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 912, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_syms)};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 912, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 912, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(((PyObject *)__pyx_v_syms));
-          __Pyx_GIVEREF(((PyObject *)__pyx_v_syms));
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, ((PyObject *)__pyx_v_syms));
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 912, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":924
+  /* "pywrapfst.pyx":933
  *       syms: A SymbolTable to be merged with the current table.
  *     """
  *     self._table.AddTable(deref(syms._table))             # <<<<<<<<<<<<<<
@@ -11772,15 +11165,15 @@ static void __pyx_f_9pywrapfst_19_MutableSymbolTable_add_table(struct __pyx_obj_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 924, __pyx_L1_error)
+    __PYX_ERR(0, 933, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_syms) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 924, __pyx_L1_error)
+    __PYX_ERR(0, 933, __pyx_L1_error)
   }
   __pyx_v_self->__pyx_base._table->AddTable((*__pyx_v_syms->_table));
 
-  /* "pywrapfst.pyx":912
+  /* "pywrapfst.pyx":921
  *       return self._table.AddSymbol(symbol_string)
  * 
  *   cpdef void add_table(self, _SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -11795,7 +11188,6 @@ static void __pyx_f_9pywrapfst_19_MutableSymbolTable_add_table(struct __pyx_obj_
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_WriteUnraisable("pywrapfst._MutableSymbolTable.add_table", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -11808,7 +11200,7 @@ static PyObject *__pyx_pw_9pywrapfst_19_MutableSymbolTable_3add_table(PyObject *
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("add_table (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 912, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 921, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_19_MutableSymbolTable_2add_table(((struct __pyx_obj_9pywrapfst__MutableSymbolTable *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_syms));
 
   /* function exit code */
@@ -11826,7 +11218,7 @@ static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_2add_table(struct __p
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("add_table", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_19_MutableSymbolTable_add_table(__pyx_v_self, __pyx_v_syms, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 912, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_19_MutableSymbolTable_add_table(__pyx_v_self, __pyx_v_syms, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 921, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -11843,7 +11235,7 @@ static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_2add_table(struct __p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":926
+/* "pywrapfst.pyx":935
  *     self._table.AddTable(deref(syms._table))
  * 
  *   cpdef void set_name(self, new_name) except *:             # <<<<<<<<<<<<<<
@@ -11858,68 +11250,55 @@ static void __pyx_f_9pywrapfst_19_MutableSymbolTable_set_name(struct __pyx_obj_9
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  std::string __pyx_t_6;
+  std::string __pyx_t_5;
   __Pyx_RefNannySetupContext("set_name", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_name); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 926, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_19_MutableSymbolTable_5set_name)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_name); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 935, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_19_MutableSymbolTable_5set_name)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_new_name); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 926, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_new_name) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_new_name);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 935, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_new_name};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 926, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_new_name};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 926, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 926, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(__pyx_v_new_name);
-          __Pyx_GIVEREF(__pyx_v_new_name);
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_v_new_name);
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 926, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":927
+  /* "pywrapfst.pyx":936
  * 
  *   cpdef void set_name(self, new_name) except *:
  *     self._table.SetName(tostring(new_name))             # <<<<<<<<<<<<<<
@@ -11928,12 +11307,12 @@ static void __pyx_f_9pywrapfst_19_MutableSymbolTable_set_name(struct __pyx_obj_9
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 927, __pyx_L1_error)
+    __PYX_ERR(0, 936, __pyx_L1_error)
   }
-  __pyx_t_6 = __pyx_f_9pywrapfst_tostring(__pyx_v_new_name, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 927, __pyx_L1_error)
-  __pyx_v_self->__pyx_base._table->SetName(__pyx_t_6);
+  __pyx_t_5 = __pyx_f_9pywrapfst_tostring(__pyx_v_new_name, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 936, __pyx_L1_error)
+  __pyx_v_self->__pyx_base._table->SetName(__pyx_t_5);
 
-  /* "pywrapfst.pyx":926
+  /* "pywrapfst.pyx":935
  *     self._table.AddTable(deref(syms._table))
  * 
  *   cpdef void set_name(self, new_name) except *:             # <<<<<<<<<<<<<<
@@ -11948,7 +11327,6 @@ static void __pyx_f_9pywrapfst_19_MutableSymbolTable_set_name(struct __pyx_obj_9
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst._MutableSymbolTable.set_name", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -11973,8 +11351,8 @@ static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_4set_name(struct __py
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("set_name", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_f_9pywrapfst_19_MutableSymbolTable_set_name(__pyx_v_self, __pyx_v_new_name, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 926, __pyx_L1_error)
-  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 926, __pyx_L1_error)
+  __pyx_f_9pywrapfst_19_MutableSymbolTable_set_name(__pyx_v_self, __pyx_v_new_name, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 935, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 935, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -11991,114 +11369,7 @@ static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_4set_name(struct __py
   return __pyx_r;
 }
 
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_19_MutableSymbolTable_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_19_MutableSymbolTable_7__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_19_MutableSymbolTable_6__reduce_cython__(((struct __pyx_obj_9pywrapfst__MutableSymbolTable *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_6__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__14, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 2, __pyx_L1_error)
-
-  /* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._MutableSymbolTable.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_19_MutableSymbolTable_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_19_MutableSymbolTable_9__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_19_MutableSymbolTable_8__setstate_cython__(((struct __pyx_obj_9pywrapfst__MutableSymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_19_MutableSymbolTable_8__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__MutableSymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__15, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 4, __pyx_L1_error)
-
-  /* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._MutableSymbolTable.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "pywrapfst.pyx":937
+/* "pywrapfst.pyx":946
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -12131,7 +11402,7 @@ static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable___repr__(struct __
   PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":938
+  /* "pywrapfst.pyx":947
  * 
  *   def __repr__(self):
  *     return "<Fst SymbolTable {!r} at 0x{:x}>".format(self.name(), id(self))             # <<<<<<<<<<<<<<
@@ -12139,15 +11410,15 @@ static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable___repr__(struct __
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Fst_SymbolTable_r_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 938, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Fst_SymbolTable_r_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 947, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "name");
-    __PYX_ERR(0, 938, __pyx_L1_error)
+    __PYX_ERR(0, 947, __pyx_L1_error)
   }
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__MutableFstSymbolTable *)__pyx_v_self->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 938, __pyx_L1_error)
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__MutableFstSymbolTable *)__pyx_v_self->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 947, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 938, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 947, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_t_5 = NULL;
   __pyx_t_6 = 0;
@@ -12164,7 +11435,7 @@ static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable___repr__(struct __
   #if CYTHON_FAST_PYCALL
   if (PyFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 938, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 947, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -12174,7 +11445,7 @@ static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable___repr__(struct __
   #if CYTHON_FAST_PYCCALL
   if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 938, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 947, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -12182,7 +11453,7 @@ static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable___repr__(struct __
   } else
   #endif
   {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 938, __pyx_L1_error)
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 947, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_7);
     if (__pyx_t_5) {
       __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
@@ -12193,7 +11464,7 @@ static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable___repr__(struct __
     PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_4);
     __pyx_t_3 = 0;
     __pyx_t_4 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 938, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 947, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   }
@@ -12202,7 +11473,7 @@ static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable___repr__(struct __
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":937
+  /* "pywrapfst.pyx":946
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -12226,114 +11497,7 @@ static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable___repr__(struct __
   return __pyx_r;
 }
 
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_22_MutableFstSymbolTable_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_22_MutableFstSymbolTable_3__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_22_MutableFstSymbolTable_2__reduce_cython__(((struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable_2__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__16, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 2, __pyx_L1_error)
-
-  /* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._MutableFstSymbolTable.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_22_MutableFstSymbolTable_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_22_MutableFstSymbolTable_5__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_22_MutableFstSymbolTable_4__setstate_cython__(((struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_22_MutableFstSymbolTable_4__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__17, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 4, __pyx_L1_error)
-
-  /* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._MutableFstSymbolTable.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "pywrapfst.pyx":958
+/* "pywrapfst.pyx":967
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -12366,23 +11530,23 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable___repr__(struct __pyx_obj_9py
   PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":959
+  /* "pywrapfst.pyx":968
  * 
  *   def __repr__(self):
  *     return "<SymbolTable {!r} at 0x{:x}>".format(self.name(), id(self))             # <<<<<<<<<<<<<<
  * 
- *   def __init__(self, name=b"<unspecified>"):
+ *   def __init__(self, name="<unspecified>"):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_SymbolTable_r_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 959, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_SymbolTable_r_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 968, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "name");
-    __PYX_ERR(0, 959, __pyx_L1_error)
+    __PYX_ERR(0, 968, __pyx_L1_error)
   }
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_SymbolTable *)__pyx_v_self->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 959, __pyx_L1_error)
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_SymbolTable *)__pyx_v_self->__pyx_base.__pyx_base.__pyx_vtab)->__pyx_base.__pyx_base.name(((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_self), 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 968, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 959, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 968, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_t_5 = NULL;
   __pyx_t_6 = 0;
@@ -12399,7 +11563,7 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable___repr__(struct __pyx_obj_9py
   #if CYTHON_FAST_PYCALL
   if (PyFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 959, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 968, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -12409,7 +11573,7 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable___repr__(struct __pyx_obj_9py
   #if CYTHON_FAST_PYCCALL
   if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 959, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 968, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -12417,7 +11581,7 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable___repr__(struct __pyx_obj_9py
   } else
   #endif
   {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 959, __pyx_L1_error)
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 968, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_7);
     if (__pyx_t_5) {
       __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
@@ -12428,7 +11592,7 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable___repr__(struct __pyx_obj_9py
     PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_4);
     __pyx_t_3 = 0;
     __pyx_t_4 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 959, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 968, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   }
@@ -12437,7 +11601,7 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable___repr__(struct __pyx_obj_9py
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":958
+  /* "pywrapfst.pyx":967
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -12461,10 +11625,10 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable___repr__(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":961
+/* "pywrapfst.pyx":970
  *     return "<SymbolTable {!r} at 0x{:x}>".format(self.name(), id(self))
  * 
- *   def __init__(self, name=b"<unspecified>"):             # <<<<<<<<<<<<<<
+ *   def __init__(self, name="<unspecified>"):             # <<<<<<<<<<<<<<
  *     self._table = new fst.SymbolTable(tostring(name))
  *     self._smart_table.reset(self._table)
  */
@@ -12479,7 +11643,7 @@ static int __pyx_pw_9pywrapfst_11SymbolTable_3__init__(PyObject *__pyx_v_self, P
   {
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_name_2,0};
     PyObject* values[1] = {0};
-    values[0] = ((PyObject *)__pyx_kp_b_unspecified);
+    values[0] = ((PyObject *)__pyx_kp_u_unspecified);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
@@ -12498,7 +11662,7 @@ static int __pyx_pw_9pywrapfst_11SymbolTable_3__init__(PyObject *__pyx_v_self, P
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 961, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 970, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -12512,7 +11676,7 @@ static int __pyx_pw_9pywrapfst_11SymbolTable_3__init__(PyObject *__pyx_v_self, P
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 961, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__init__", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 970, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.SymbolTable.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -12531,22 +11695,22 @@ static int __pyx_pf_9pywrapfst_11SymbolTable_2__init__(struct __pyx_obj_9pywrapf
   std::string __pyx_t_1;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":962
+  /* "pywrapfst.pyx":971
  * 
- *   def __init__(self, name=b"<unspecified>"):
+ *   def __init__(self, name="<unspecified>"):
  *     self._table = new fst.SymbolTable(tostring(name))             # <<<<<<<<<<<<<<
  *     self._smart_table.reset(self._table)
  * 
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_name, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 962, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_name, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 971, __pyx_L1_error)
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 962, __pyx_L1_error)
+    __PYX_ERR(0, 971, __pyx_L1_error)
   }
   __pyx_v_self->__pyx_base.__pyx_base._table = new fst::SymbolTable(__pyx_t_1);
 
-  /* "pywrapfst.pyx":963
- *   def __init__(self, name=b"<unspecified>"):
+  /* "pywrapfst.pyx":972
+ *   def __init__(self, name="<unspecified>"):
  *     self._table = new fst.SymbolTable(tostring(name))
  *     self._smart_table.reset(self._table)             # <<<<<<<<<<<<<<
  * 
@@ -12554,18 +11718,18 @@ static int __pyx_pf_9pywrapfst_11SymbolTable_2__init__(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_smart_table");
-    __PYX_ERR(0, 963, __pyx_L1_error)
+    __PYX_ERR(0, 972, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 963, __pyx_L1_error)
+    __PYX_ERR(0, 972, __pyx_L1_error)
   }
   __pyx_v_self->_smart_table.reset(__pyx_v_self->__pyx_base.__pyx_base._table);
 
-  /* "pywrapfst.pyx":961
+  /* "pywrapfst.pyx":970
  *     return "<SymbolTable {!r} at 0x{:x}>".format(self.name(), id(self))
  * 
- *   def __init__(self, name=b"<unspecified>"):             # <<<<<<<<<<<<<<
+ *   def __init__(self, name="<unspecified>"):             # <<<<<<<<<<<<<<
  *     self._table = new fst.SymbolTable(tostring(name))
  *     self._smart_table.reset(self._table)
  */
@@ -12581,7 +11745,7 @@ static int __pyx_pf_9pywrapfst_11SymbolTable_2__init__(struct __pyx_obj_9pywrapf
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":966
+/* "pywrapfst.pyx":975
  * 
  *   @classmethod
  *   def read(cls, filename):             # <<<<<<<<<<<<<<
@@ -12604,7 +11768,7 @@ static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_5read(PyObject *__pyx_v_cls,
 }
 
 static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_4read(CYTHON_UNUSED PyTypeObject *__pyx_v_cls, PyObject *__pyx_v_filename) {
-  fst::SymbolTable *__pyx_v_tsyms;
+  std::unique_ptr<fst::SymbolTable>  __pyx_v_syms;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   std::string __pyx_t_1;
@@ -12614,39 +11778,38 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_4read(CYTHON_UNUSED PyTypeObj
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("read", 0);
 
-  /* "pywrapfst.pyx":982
- *     See also: `SymbolTable.read_fst`, `SymbolTable.read_text`.
+  /* "pywrapfst.pyx":992
  *     """
- *     cdef fst.SymbolTable *tsyms = fst.SymbolTable.Read(tostring(filename))             # <<<<<<<<<<<<<<
- *     if tsyms == NULL:
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.SymbolTable.Read(tostring(filename)))             # <<<<<<<<<<<<<<
+ *     if syms.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filename))
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 982, __pyx_L1_error)
-  __pyx_v_tsyms = fst::SymbolTable::Read(__pyx_t_1);
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 992, __pyx_L1_error)
+  __pyx_v_syms.reset(fst::SymbolTable::Read(__pyx_t_1));
 
-  /* "pywrapfst.pyx":983
- *     """
- *     cdef fst.SymbolTable *tsyms = fst.SymbolTable.Read(tostring(filename))
- *     if tsyms == NULL:             # <<<<<<<<<<<<<<
+  /* "pywrapfst.pyx":993
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.SymbolTable.Read(tostring(filename)))
+ *     if syms.get() == NULL:             # <<<<<<<<<<<<<<
  *       raise FstIOError("Read failed: {!r}".format(filename))
- *     return _init_SymbolTable(tsyms)
+ *     return _init_SymbolTable(syms.release())
  */
-  __pyx_t_2 = ((__pyx_v_tsyms == NULL) != 0);
+  __pyx_t_2 = ((__pyx_v_syms.get() == NULL) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":984
- *     cdef fst.SymbolTable *tsyms = fst.SymbolTable.Read(tostring(filename))
- *     if tsyms == NULL:
+    /* "pywrapfst.pyx":994
+ *     syms.reset(fst.SymbolTable.Read(tostring(filename)))
+ *     if syms.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filename))             # <<<<<<<<<<<<<<
- *     return _init_SymbolTable(tsyms)
+ *     return _init_SymbolTable(syms.release())
  * 
  */
-    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 984, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 994, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 984, __pyx_L1_error)
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 994, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
@@ -12658,38 +11821,10 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_4read(CYTHON_UNUSED PyTypeObj
         __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_filename); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 984, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_filename};
-        __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 984, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_filename};
-        __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 984, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 984, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_INCREF(__pyx_v_filename);
-        __Pyx_GIVEREF(__pyx_v_filename);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_filename);
-        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 984, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_filename);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 994, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
@@ -12701,70 +11836,40 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_4read(CYTHON_UNUSED PyTypeObj
         __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 984, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 984, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 984, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 984, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_5);
-        __pyx_t_5 = 0;
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 984, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 994, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 984, __pyx_L1_error)
+    __PYX_ERR(0, 994, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":983
- *     """
- *     cdef fst.SymbolTable *tsyms = fst.SymbolTable.Read(tostring(filename))
- *     if tsyms == NULL:             # <<<<<<<<<<<<<<
+    /* "pywrapfst.pyx":993
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.SymbolTable.Read(tostring(filename)))
+ *     if syms.get() == NULL:             # <<<<<<<<<<<<<<
  *       raise FstIOError("Read failed: {!r}".format(filename))
- *     return _init_SymbolTable(tsyms)
+ *     return _init_SymbolTable(syms.release())
  */
   }
 
-  /* "pywrapfst.pyx":985
- *     if tsyms == NULL:
+  /* "pywrapfst.pyx":995
+ *     if syms.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filename))
- *     return _init_SymbolTable(tsyms)             # <<<<<<<<<<<<<<
+ *     return _init_SymbolTable(syms.release())             # <<<<<<<<<<<<<<
  * 
  *   @classmethod
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(__pyx_v_tsyms)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 985, __pyx_L1_error)
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(__pyx_v_syms.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 995, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":966
+  /* "pywrapfst.pyx":975
  * 
  *   @classmethod
  *   def read(cls, filename):             # <<<<<<<<<<<<<<
@@ -12779,7 +11884,6 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_4read(CYTHON_UNUSED PyTypeObj
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst.SymbolTable.read", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -12788,7 +11892,7 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_4read(CYTHON_UNUSED PyTypeObj
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":988
+/* "pywrapfst.pyx":998
  * 
  *   @classmethod
  *   def read_text(cls, filename, bool allow_negative_labels=False):             # <<<<<<<<<<<<<<
@@ -12832,7 +11936,7 @@ static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_7read_text(PyObject *__pyx_v_
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "read_text") < 0)) __PYX_ERR(0, 988, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "read_text") < 0)) __PYX_ERR(0, 998, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -12845,14 +11949,14 @@ static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_7read_text(PyObject *__pyx_v_
     }
     __pyx_v_filename = values[0];
     if (values[1]) {
-      __pyx_v_allow_negative_labels = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_allow_negative_labels == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 988, __pyx_L3_error)
+      __pyx_v_allow_negative_labels = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_allow_negative_labels == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 998, __pyx_L3_error)
     } else {
       __pyx_v_allow_negative_labels = ((bool)0);
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("read_text", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 988, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("read_text", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 998, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.SymbolTable.read_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -12867,7 +11971,7 @@ static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_7read_text(PyObject *__pyx_v_
 
 static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_6read_text(CYTHON_UNUSED PyTypeObject *__pyx_v_cls, PyObject *__pyx_v_filename, bool __pyx_v_allow_negative_labels) {
   std::unique_ptr<fst::SymbolTableTextOptions>  __pyx_v_opts;
-  fst::SymbolTable *__pyx_v_tsyms;
+  std::unique_ptr<fst::SymbolTable>  __pyx_v_syms;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   std::string __pyx_t_1;
@@ -12877,56 +11981,47 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_6read_text(CYTHON_UNUSED PyTy
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("read_text", 0);
 
-  /* "pywrapfst.pyx":1007
+  /* "pywrapfst.pyx":1017
  *     """
  *     cdef unique_ptr[fst.SymbolTableTextOptions] opts
  *     opts.reset(new fst.SymbolTableTextOptions(allow_negative_labels))             # <<<<<<<<<<<<<<
- *     cdef fst.SymbolTable *tsyms = fst.SymbolTable.ReadText(tostring(filename),
- *                                                            deref(opts))
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.SymbolTable.ReadText(tostring(filename), deref(opts)))
  */
   __pyx_v_opts.reset(new fst::SymbolTableTextOptions(__pyx_v_allow_negative_labels));
 
-  /* "pywrapfst.pyx":1008
- *     cdef unique_ptr[fst.SymbolTableTextOptions] opts
- *     opts.reset(new fst.SymbolTableTextOptions(allow_negative_labels))
- *     cdef fst.SymbolTable *tsyms = fst.SymbolTable.ReadText(tostring(filename),             # <<<<<<<<<<<<<<
- *                                                            deref(opts))
- *     if tsyms == NULL:
- */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1008, __pyx_L1_error)
-
-  /* "pywrapfst.pyx":1009
+  /* "pywrapfst.pyx":1019
  *     opts.reset(new fst.SymbolTableTextOptions(allow_negative_labels))
- *     cdef fst.SymbolTable *tsyms = fst.SymbolTable.ReadText(tostring(filename),
- *                                                            deref(opts))             # <<<<<<<<<<<<<<
- *     if tsyms == NULL:
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.SymbolTable.ReadText(tostring(filename), deref(opts)))             # <<<<<<<<<<<<<<
+ *     if syms.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filename))
  */
-  __pyx_v_tsyms = fst::SymbolTable::ReadText(__pyx_t_1, (*__pyx_v_opts));
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1019, __pyx_L1_error)
+  __pyx_v_syms.reset(fst::SymbolTable::ReadText(__pyx_t_1, (*__pyx_v_opts)));
 
-  /* "pywrapfst.pyx":1010
- *     cdef fst.SymbolTable *tsyms = fst.SymbolTable.ReadText(tostring(filename),
- *                                                            deref(opts))
- *     if tsyms == NULL:             # <<<<<<<<<<<<<<
+  /* "pywrapfst.pyx":1020
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.SymbolTable.ReadText(tostring(filename), deref(opts)))
+ *     if syms.get() == NULL:             # <<<<<<<<<<<<<<
  *       raise FstIOError("Read failed: {!r}".format(filename))
- *     return _init_SymbolTable(tsyms)
+ *     return _init_SymbolTable(syms.release())
  */
-  __pyx_t_2 = ((__pyx_v_tsyms == NULL) != 0);
+  __pyx_t_2 = ((__pyx_v_syms.get() == NULL) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":1011
- *                                                            deref(opts))
- *     if tsyms == NULL:
+    /* "pywrapfst.pyx":1021
+ *     syms.reset(fst.SymbolTable.ReadText(tostring(filename), deref(opts)))
+ *     if syms.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filename))             # <<<<<<<<<<<<<<
- *     return _init_SymbolTable(tsyms)
+ *     return _init_SymbolTable(syms.release())
  * 
  */
-    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1011, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1021, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1011, __pyx_L1_error)
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1021, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
@@ -12938,38 +12033,10 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_6read_text(CYTHON_UNUSED PyTy
         __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_filename); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1011, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_filename};
-        __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1011, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_filename};
-        __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1011, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1011, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_INCREF(__pyx_v_filename);
-        __Pyx_GIVEREF(__pyx_v_filename);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_filename);
-        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1011, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_filename);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1021, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
@@ -12981,70 +12048,40 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_6read_text(CYTHON_UNUSED PyTy
         __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1011, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1011, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1011, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1011, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_5);
-        __pyx_t_5 = 0;
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1011, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1021, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 1011, __pyx_L1_error)
+    __PYX_ERR(0, 1021, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1010
- *     cdef fst.SymbolTable *tsyms = fst.SymbolTable.ReadText(tostring(filename),
- *                                                            deref(opts))
- *     if tsyms == NULL:             # <<<<<<<<<<<<<<
+    /* "pywrapfst.pyx":1020
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.SymbolTable.ReadText(tostring(filename), deref(opts)))
+ *     if syms.get() == NULL:             # <<<<<<<<<<<<<<
  *       raise FstIOError("Read failed: {!r}".format(filename))
- *     return _init_SymbolTable(tsyms)
+ *     return _init_SymbolTable(syms.release())
  */
   }
 
-  /* "pywrapfst.pyx":1012
- *     if tsyms == NULL:
+  /* "pywrapfst.pyx":1022
+ *     if syms.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filename))
- *     return _init_SymbolTable(tsyms)             # <<<<<<<<<<<<<<
+ *     return _init_SymbolTable(syms.release())             # <<<<<<<<<<<<<<
  * 
  *   @classmethod
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(__pyx_v_tsyms)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1012, __pyx_L1_error)
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(__pyx_v_syms.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1022, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":988
+  /* "pywrapfst.pyx":998
  * 
  *   @classmethod
  *   def read_text(cls, filename, bool allow_negative_labels=False):             # <<<<<<<<<<<<<<
@@ -13059,7 +12096,6 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_6read_text(CYTHON_UNUSED PyTy
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst.SymbolTable.read_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -13068,7 +12104,7 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_6read_text(CYTHON_UNUSED PyTy
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1015
+/* "pywrapfst.pyx":1025
  * 
  *   @classmethod
  *   def read_fst(cls, filename, bool input_table):             # <<<<<<<<<<<<<<
@@ -13108,11 +12144,11 @@ static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_9read_fst(PyObject *__pyx_v_c
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_input_table)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("read_fst", 1, 2, 2, 1); __PYX_ERR(0, 1015, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("read_fst", 1, 2, 2, 1); __PYX_ERR(0, 1025, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "read_fst") < 0)) __PYX_ERR(0, 1015, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "read_fst") < 0)) __PYX_ERR(0, 1025, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -13121,11 +12157,11 @@ static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_9read_fst(PyObject *__pyx_v_c
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
     __pyx_v_filename = values[0];
-    __pyx_v_input_table = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_input_table == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1015, __pyx_L3_error)
+    __pyx_v_input_table = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_input_table == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1025, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("read_fst", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1015, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("read_fst", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1025, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.SymbolTable.read_fst", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -13139,7 +12175,7 @@ static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_9read_fst(PyObject *__pyx_v_c
 }
 
 static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_8read_fst(CYTHON_UNUSED PyTypeObject *__pyx_v_cls, PyObject *__pyx_v_filename, bool __pyx_v_input_table) {
-  fst::SymbolTable *__pyx_v_tsyms;
+  std::unique_ptr<fst::SymbolTable>  __pyx_v_syms;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   std::string __pyx_t_1;
@@ -13149,39 +12185,38 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_8read_fst(CYTHON_UNUSED PyTyp
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("read_fst", 0);
 
-  /* "pywrapfst.pyx":1037
- *     See also: `SymbolTable.read`, `SymbolTable.read_text`.
+  /* "pywrapfst.pyx":1048
  *     """
- *     cdef fst.SymbolTable *tsyms = fst.FstReadSymbols(filename, input_table)             # <<<<<<<<<<<<<<
- *     if tsyms == NULL:
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.FstReadSymbols(tostring(filename), input_table))             # <<<<<<<<<<<<<<
+ *     if syms.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filename))
  */
-  __pyx_t_1 = __pyx_convert_string_from_py_std__in_string(__pyx_v_filename); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1037, __pyx_L1_error)
-  __pyx_v_tsyms = fst::FstReadSymbols(__pyx_t_1, __pyx_v_input_table);
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1048, __pyx_L1_error)
+  __pyx_v_syms.reset(fst::FstReadSymbols(__pyx_t_1, __pyx_v_input_table));
 
-  /* "pywrapfst.pyx":1038
- *     """
- *     cdef fst.SymbolTable *tsyms = fst.FstReadSymbols(filename, input_table)
- *     if tsyms == NULL:             # <<<<<<<<<<<<<<
+  /* "pywrapfst.pyx":1049
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.FstReadSymbols(tostring(filename), input_table))
+ *     if syms.get() == NULL:             # <<<<<<<<<<<<<<
  *       raise FstIOError("Read failed: {!r}".format(filename))
- *     return _init_SymbolTable(tsyms)
+ *     return _init_SymbolTable(syms.release())
  */
-  __pyx_t_2 = ((__pyx_v_tsyms == NULL) != 0);
+  __pyx_t_2 = ((__pyx_v_syms.get() == NULL) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":1039
- *     cdef fst.SymbolTable *tsyms = fst.FstReadSymbols(filename, input_table)
- *     if tsyms == NULL:
+    /* "pywrapfst.pyx":1050
+ *     syms.reset(fst.FstReadSymbols(tostring(filename), input_table))
+ *     if syms.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filename))             # <<<<<<<<<<<<<<
- *     return _init_SymbolTable(tsyms)
+ *     return _init_SymbolTable(syms.release())
  * 
  */
-    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1039, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1050, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1039, __pyx_L1_error)
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1050, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
@@ -13193,38 +12228,10 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_8read_fst(CYTHON_UNUSED PyTyp
         __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_filename); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1039, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_filename};
-        __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1039, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_filename};
-        __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1039, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1039, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_INCREF(__pyx_v_filename);
-        __Pyx_GIVEREF(__pyx_v_filename);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_filename);
-        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1039, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_filename);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1050, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
@@ -13236,70 +12243,40 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_8read_fst(CYTHON_UNUSED PyTyp
         __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1039, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1039, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1039, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1039, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_5);
-        __pyx_t_5 = 0;
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1039, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1050, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 1039, __pyx_L1_error)
+    __PYX_ERR(0, 1050, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1038
- *     """
- *     cdef fst.SymbolTable *tsyms = fst.FstReadSymbols(filename, input_table)
- *     if tsyms == NULL:             # <<<<<<<<<<<<<<
+    /* "pywrapfst.pyx":1049
+ *     cdef unique_ptr[fst.SymbolTable] syms
+ *     syms.reset(fst.FstReadSymbols(tostring(filename), input_table))
+ *     if syms.get() == NULL:             # <<<<<<<<<<<<<<
  *       raise FstIOError("Read failed: {!r}".format(filename))
- *     return _init_SymbolTable(tsyms)
+ *     return _init_SymbolTable(syms.release())
  */
   }
 
-  /* "pywrapfst.pyx":1040
- *     if tsyms == NULL:
+  /* "pywrapfst.pyx":1051
+ *     if syms.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filename))
- *     return _init_SymbolTable(tsyms)             # <<<<<<<<<<<<<<
+ *     return _init_SymbolTable(syms.release())             # <<<<<<<<<<<<<<
  * 
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(__pyx_v_tsyms)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1040, __pyx_L1_error)
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(__pyx_v_syms.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1051, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1015
+  /* "pywrapfst.pyx":1025
  * 
  *   @classmethod
  *   def read_fst(cls, filename, bool input_table):             # <<<<<<<<<<<<<<
@@ -13314,7 +12291,6 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_8read_fst(CYTHON_UNUSED PyTyp
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst.SymbolTable.read_fst", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -13323,114 +12299,7 @@ static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_8read_fst(CYTHON_UNUSED PyTyp
   return __pyx_r;
 }
 
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_11__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_11__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_11SymbolTable_10__reduce_cython__(((struct __pyx_obj_9pywrapfst_SymbolTable *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_10__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__18, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 2, __pyx_L1_error)
-
-  /* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst.SymbolTable.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_13__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_11SymbolTable_13__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_11SymbolTable_12__setstate_cython__(((struct __pyx_obj_9pywrapfst_SymbolTable *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_11SymbolTable_12__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__19, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(1, 4, __pyx_L1_error)
-
-  /* "(tree fragment)":3
- * def __reduce_cython__(self):
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst.SymbolTable.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "pywrapfst.pyx":1043
+/* "pywrapfst.pyx":1054
  * 
  * 
  * cdef _EncodeMapperSymbolTable _init_EncodeMapperSymbolTable(             # <<<<<<<<<<<<<<
@@ -13445,19 +12314,19 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("_init_EncodeMapperSymbolTable", 0);
 
-  /* "pywrapfst.pyx":1046
+  /* "pywrapfst.pyx":1057
  *     fst.SymbolTable *table, shared_ptr[fst.EncodeMapperClass] encoder):
  *   cdef _EncodeMapperSymbolTable result = (
  *       _EncodeMapperSymbolTable.__new__(_EncodeMapperSymbolTable))             # <<<<<<<<<<<<<<
  *   result._table = table
  *   result._encoder = encoder
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst__EncodeMapperSymbolTable(((PyTypeObject *)__pyx_ptype_9pywrapfst__EncodeMapperSymbolTable), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1046, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst__EncodeMapperSymbolTable(((PyTypeObject *)__pyx_ptype_9pywrapfst__EncodeMapperSymbolTable), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1057, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":1047
+  /* "pywrapfst.pyx":1058
  *   cdef _EncodeMapperSymbolTable result = (
  *       _EncodeMapperSymbolTable.__new__(_EncodeMapperSymbolTable))
  *   result._table = table             # <<<<<<<<<<<<<<
@@ -13466,11 +12335,11 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1047, __pyx_L1_error)
+    __PYX_ERR(0, 1058, __pyx_L1_error)
   }
   __pyx_v_result->__pyx_base._table = __pyx_v_table;
 
-  /* "pywrapfst.pyx":1048
+  /* "pywrapfst.pyx":1059
  *       _EncodeMapperSymbolTable.__new__(_EncodeMapperSymbolTable))
  *   result._table = table
  *   result._encoder = encoder             # <<<<<<<<<<<<<<
@@ -13479,11 +12348,11 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1048, __pyx_L1_error)
+    __PYX_ERR(0, 1059, __pyx_L1_error)
   }
   __pyx_v_result->_encoder = __pyx_v_encoder;
 
-  /* "pywrapfst.pyx":1049
+  /* "pywrapfst.pyx":1060
  *   result._table = table
  *   result._encoder = encoder
  *   return result             # <<<<<<<<<<<<<<
@@ -13495,7 +12364,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1043
+  /* "pywrapfst.pyx":1054
  * 
  * 
  * cdef _EncodeMapperSymbolTable _init_EncodeMapperSymbolTable(             # <<<<<<<<<<<<<<
@@ -13515,7 +12384,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1052
+/* "pywrapfst.pyx":1063
  * 
  * 
  * cdef _FstSymbolTable _init_FstSymbolTable(fst.SymbolTable *table,             # <<<<<<<<<<<<<<
@@ -13530,19 +12399,19 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst__init_Fst
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("_init_FstSymbolTable", 0);
 
-  /* "pywrapfst.pyx":1054
+  /* "pywrapfst.pyx":1065
  * cdef _FstSymbolTable _init_FstSymbolTable(fst.SymbolTable *table,
  *                                           shared_ptr[fst.FstClass] ifst):
  *   cdef _FstSymbolTable result = _FstSymbolTable.__new__(_FstSymbolTable)             # <<<<<<<<<<<<<<
  *   result._table = table
  *   result._fst = ifst
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst__FstSymbolTable(((PyTypeObject *)__pyx_ptype_9pywrapfst__FstSymbolTable), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1054, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst__FstSymbolTable(((PyTypeObject *)__pyx_ptype_9pywrapfst__FstSymbolTable), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1065, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst__FstSymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":1055
+  /* "pywrapfst.pyx":1066
  *                                           shared_ptr[fst.FstClass] ifst):
  *   cdef _FstSymbolTable result = _FstSymbolTable.__new__(_FstSymbolTable)
  *   result._table = table             # <<<<<<<<<<<<<<
@@ -13551,11 +12420,11 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst__init_Fst
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1055, __pyx_L1_error)
+    __PYX_ERR(0, 1066, __pyx_L1_error)
   }
   __pyx_v_result->__pyx_base._table = __pyx_v_table;
 
-  /* "pywrapfst.pyx":1056
+  /* "pywrapfst.pyx":1067
  *   cdef _FstSymbolTable result = _FstSymbolTable.__new__(_FstSymbolTable)
  *   result._table = table
  *   result._fst = ifst             # <<<<<<<<<<<<<<
@@ -13564,11 +12433,11 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst__init_Fst
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1056, __pyx_L1_error)
+    __PYX_ERR(0, 1067, __pyx_L1_error)
   }
   __pyx_v_result->_fst = __pyx_v_ifst;
 
-  /* "pywrapfst.pyx":1057
+  /* "pywrapfst.pyx":1068
  *   result._table = table
  *   result._fst = ifst
  *   return result             # <<<<<<<<<<<<<<
@@ -13580,7 +12449,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst__init_Fst
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1052
+  /* "pywrapfst.pyx":1063
  * 
  * 
  * cdef _FstSymbolTable _init_FstSymbolTable(fst.SymbolTable *table,             # <<<<<<<<<<<<<<
@@ -13600,7 +12469,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst__init_Fst
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1060
+/* "pywrapfst.pyx":1071
  * 
  * 
  * cdef _MutableFstSymbolTable _init_MutableFstSymbolTable(fst.SymbolTable *table,             # <<<<<<<<<<<<<<
@@ -13615,19 +12484,19 @@ static struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_f_9pywrapfst__i
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("_init_MutableFstSymbolTable", 0);
 
-  /* "pywrapfst.pyx":1063
+  /* "pywrapfst.pyx":1074
  *     shared_ptr[fst.MutableFstClass] ifst):
  *   cdef _MutableFstSymbolTable result = (
  *       _MutableFstSymbolTable.__new__(_MutableFstSymbolTable))             # <<<<<<<<<<<<<<
  *   result._table = table
  *   result._mfst = ifst
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst__MutableFstSymbolTable(((PyTypeObject *)__pyx_ptype_9pywrapfst__MutableFstSymbolTable), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1063, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst__MutableFstSymbolTable(((PyTypeObject *)__pyx_ptype_9pywrapfst__MutableFstSymbolTable), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1074, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":1064
+  /* "pywrapfst.pyx":1075
  *   cdef _MutableFstSymbolTable result = (
  *       _MutableFstSymbolTable.__new__(_MutableFstSymbolTable))
  *   result._table = table             # <<<<<<<<<<<<<<
@@ -13636,11 +12505,11 @@ static struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_f_9pywrapfst__i
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1064, __pyx_L1_error)
+    __PYX_ERR(0, 1075, __pyx_L1_error)
   }
   __pyx_v_result->__pyx_base.__pyx_base._table = __pyx_v_table;
 
-  /* "pywrapfst.pyx":1065
+  /* "pywrapfst.pyx":1076
  *       _MutableFstSymbolTable.__new__(_MutableFstSymbolTable))
  *   result._table = table
  *   result._mfst = ifst             # <<<<<<<<<<<<<<
@@ -13649,11 +12518,11 @@ static struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_f_9pywrapfst__i
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 1065, __pyx_L1_error)
+    __PYX_ERR(0, 1076, __pyx_L1_error)
   }
   __pyx_v_result->_mfst = __pyx_v_ifst;
 
-  /* "pywrapfst.pyx":1066
+  /* "pywrapfst.pyx":1077
  *   result._table = table
  *   result._mfst = ifst
  *   return result             # <<<<<<<<<<<<<<
@@ -13665,7 +12534,7 @@ static struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_f_9pywrapfst__i
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1060
+  /* "pywrapfst.pyx":1071
  * 
  * 
  * cdef _MutableFstSymbolTable _init_MutableFstSymbolTable(fst.SymbolTable *table,             # <<<<<<<<<<<<<<
@@ -13685,7 +12554,7 @@ static struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *__pyx_f_9pywrapfst__i
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1069
+/* "pywrapfst.pyx":1080
  * 
  * 
  * cdef SymbolTable _init_SymbolTable(fst.SymbolTable *table):             # <<<<<<<<<<<<<<
@@ -13700,19 +12569,19 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst__init_SymbolT
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("_init_SymbolTable", 0);
 
-  /* "pywrapfst.pyx":1070
+  /* "pywrapfst.pyx":1081
  * 
  * cdef SymbolTable _init_SymbolTable(fst.SymbolTable *table):
  *   cdef SymbolTable result = SymbolTable.__new__(SymbolTable)             # <<<<<<<<<<<<<<
  *   result._table = table
  *   return result
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_SymbolTable(((PyTypeObject *)__pyx_ptype_9pywrapfst_SymbolTable), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1070, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_SymbolTable(((PyTypeObject *)__pyx_ptype_9pywrapfst_SymbolTable), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1081, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_SymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":1071
+  /* "pywrapfst.pyx":1082
  * cdef SymbolTable _init_SymbolTable(fst.SymbolTable *table):
  *   cdef SymbolTable result = SymbolTable.__new__(SymbolTable)
  *   result._table = table             # <<<<<<<<<<<<<<
@@ -13721,11 +12590,11 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst__init_SymbolT
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1071, __pyx_L1_error)
+    __PYX_ERR(0, 1082, __pyx_L1_error)
   }
   __pyx_v_result->__pyx_base.__pyx_base._table = __pyx_v_table;
 
-  /* "pywrapfst.pyx":1072
+  /* "pywrapfst.pyx":1083
  *   cdef SymbolTable result = SymbolTable.__new__(SymbolTable)
  *   result._table = table
  *   return result             # <<<<<<<<<<<<<<
@@ -13737,7 +12606,7 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst__init_SymbolT
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1069
+  /* "pywrapfst.pyx":1080
  * 
  * 
  * cdef SymbolTable _init_SymbolTable(fst.SymbolTable *table):             # <<<<<<<<<<<<<<
@@ -13757,7 +12626,165 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst__init_SymbolT
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1078
+/* "pywrapfst.pyx":1086
+ * 
+ * 
+ * cpdef SymbolTable _read_SymbolTable_from_string(state):             # <<<<<<<<<<<<<<
+ *   cdef stringstream sstrm
+ *   sstrm << tostring(state)
+ */
+
+static PyObject *__pyx_pw_9pywrapfst_9_read_SymbolTable_from_string(PyObject *__pyx_self, PyObject *__pyx_v_state); /*proto*/
+static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst__read_SymbolTable_from_string(PyObject *__pyx_v_state, CYTHON_UNUSED int __pyx_skip_dispatch) {
+  std::stringstream __pyx_v_sstrm;
+  std::unique_ptr<fst::SymbolTable>  __pyx_v_syms;
+  struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  std::string __pyx_t_1;
+  int __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  __Pyx_RefNannySetupContext("_read_SymbolTable_from_string", 0);
+
+  /* "pywrapfst.pyx":1088
+ * cpdef SymbolTable _read_SymbolTable_from_string(state):
+ *   cdef stringstream sstrm
+ *   sstrm << tostring(state)             # <<<<<<<<<<<<<<
+ *   cdef unique_ptr[fst.SymbolTable] syms
+ *   syms.reset(fst.SymbolTable.ReadStream(sstrm, b"<pywrapfst>"))
+ */
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_state, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1088, __pyx_L1_error)
+  (void)((__pyx_v_sstrm << __pyx_t_1));
+
+  /* "pywrapfst.pyx":1090
+ *   sstrm << tostring(state)
+ *   cdef unique_ptr[fst.SymbolTable] syms
+ *   syms.reset(fst.SymbolTable.ReadStream(sstrm, b"<pywrapfst>"))             # <<<<<<<<<<<<<<
+ *   if syms.get() == NULL:
+ *     raise FstIOError("Read failed")
+ */
+  __pyx_v_syms.reset(fst::SymbolTable::Read(__pyx_v_sstrm, __pyx_k_pywrapfst));
+
+  /* "pywrapfst.pyx":1091
+ *   cdef unique_ptr[fst.SymbolTable] syms
+ *   syms.reset(fst.SymbolTable.ReadStream(sstrm, b"<pywrapfst>"))
+ *   if syms.get() == NULL:             # <<<<<<<<<<<<<<
+ *     raise FstIOError("Read failed")
+ *   return _init_SymbolTable(syms.release())
+ */
+  __pyx_t_2 = ((__pyx_v_syms.get() == NULL) != 0);
+  if (unlikely(__pyx_t_2)) {
+
+    /* "pywrapfst.pyx":1092
+ *   syms.reset(fst.SymbolTable.ReadStream(sstrm, b"<pywrapfst>"))
+ *   if syms.get() == NULL:
+ *     raise FstIOError("Read failed")             # <<<<<<<<<<<<<<
+ *   return _init_SymbolTable(syms.release())
+ * 
+ */
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1092, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_u_Read_failed) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_u_Read_failed);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1092, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __PYX_ERR(0, 1092, __pyx_L1_error)
+
+    /* "pywrapfst.pyx":1091
+ *   cdef unique_ptr[fst.SymbolTable] syms
+ *   syms.reset(fst.SymbolTable.ReadStream(sstrm, b"<pywrapfst>"))
+ *   if syms.get() == NULL:             # <<<<<<<<<<<<<<
+ *     raise FstIOError("Read failed")
+ *   return _init_SymbolTable(syms.release())
+ */
+  }
+
+  /* "pywrapfst.pyx":1093
+ *   if syms.get() == NULL:
+ *     raise FstIOError("Read failed")
+ *   return _init_SymbolTable(syms.release())             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(((PyObject *)__pyx_r));
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(__pyx_v_syms.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1093, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_r = ((struct __pyx_obj_9pywrapfst_SymbolTable *)__pyx_t_3);
+  __pyx_t_3 = 0;
+  goto __pyx_L0;
+
+  /* "pywrapfst.pyx":1086
+ * 
+ * 
+ * cpdef SymbolTable _read_SymbolTable_from_string(state):             # <<<<<<<<<<<<<<
+ *   cdef stringstream sstrm
+ *   sstrm << tostring(state)
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("pywrapfst._read_SymbolTable_from_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF((PyObject *)__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9pywrapfst_9_read_SymbolTable_from_string(PyObject *__pyx_self, PyObject *__pyx_v_state); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_9_read_SymbolTable_from_string(PyObject *__pyx_self, PyObject *__pyx_v_state) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("_read_SymbolTable_from_string (wrapper)", 0);
+  __pyx_r = __pyx_pf_9pywrapfst_8_read_SymbolTable_from_string(__pyx_self, ((PyObject *)__pyx_v_state));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9pywrapfst_8_read_SymbolTable_from_string(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_state) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  __Pyx_RefNannySetupContext("_read_SymbolTable_from_string", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__read_SymbolTable_from_string(__pyx_v_state, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1086, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pywrapfst._read_SymbolTable_from_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pywrapfst.pyx":1099
  * 
  * 
  * cpdef SymbolTable compact_symbol_table(_SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -13765,14 +12792,14 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst__init_SymbolT
  *   compact_symbol_table(syms)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_9compact_symbol_table(PyObject *__pyx_self, PyObject *__pyx_v_syms); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_11compact_symbol_table(PyObject *__pyx_self, PyObject *__pyx_v_syms); /*proto*/
 static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_compact_symbol_table(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms, CYTHON_UNUSED int __pyx_skip_dispatch) {
   struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("compact_symbol_table", 0);
 
-  /* "pywrapfst.pyx":1090
+  /* "pywrapfst.pyx":1111
  *     A new compacted SymbolTable.
  *   """
  *   return _init_SymbolTable(fst.CompactSymbolTable(deref(syms._table)))             # <<<<<<<<<<<<<<
@@ -13782,15 +12809,15 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_compact_symbo
   __Pyx_XDECREF(((PyObject *)__pyx_r));
   if (unlikely(((PyObject *)__pyx_v_syms) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1090, __pyx_L1_error)
+    __PYX_ERR(0, 1111, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(fst::CompactSymbolTable((*__pyx_v_syms->_table)))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1090, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(fst::CompactSymbolTable((*__pyx_v_syms->_table)))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1111, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst_SymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1078
+  /* "pywrapfst.pyx":1099
  * 
  * 
  * cpdef SymbolTable compact_symbol_table(_SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -13810,14 +12837,14 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_compact_symbo
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_9compact_symbol_table(PyObject *__pyx_self, PyObject *__pyx_v_syms); /*proto*/
-static char __pyx_doc_9pywrapfst_8compact_symbol_table[] = "\n  compact_symbol_table(syms)\n\n  Constructively relabels a SymbolTable to make it a contiguous mapping.\n\n  Args:\n    syms: Input SymbolTable.\n\n  Returns:\n    A new compacted SymbolTable.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_9compact_symbol_table(PyObject *__pyx_self, PyObject *__pyx_v_syms) {
+static PyObject *__pyx_pw_9pywrapfst_11compact_symbol_table(PyObject *__pyx_self, PyObject *__pyx_v_syms); /*proto*/
+static char __pyx_doc_9pywrapfst_10compact_symbol_table[] = "\n  compact_symbol_table(syms)\n\n  Constructively relabels a SymbolTable to make it a contiguous mapping.\n\n  Args:\n    syms: Input SymbolTable.\n\n  Returns:\n    A new compacted SymbolTable.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_11compact_symbol_table(PyObject *__pyx_self, PyObject *__pyx_v_syms) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("compact_symbol_table (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 1078, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_8compact_symbol_table(__pyx_self, ((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_syms));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 1099, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_10compact_symbol_table(__pyx_self, ((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_syms));
 
   /* function exit code */
   goto __pyx_L0;
@@ -13828,13 +12855,13 @@ static PyObject *__pyx_pw_9pywrapfst_9compact_symbol_table(PyObject *__pyx_self,
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_8compact_symbol_table(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms) {
+static PyObject *__pyx_pf_9pywrapfst_10compact_symbol_table(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_syms) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("compact_symbol_table", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_compact_symbol_table(__pyx_v_syms, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1078, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_compact_symbol_table(__pyx_v_syms, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1099, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -13851,7 +12878,7 @@ static PyObject *__pyx_pf_9pywrapfst_8compact_symbol_table(CYTHON_UNUSED PyObjec
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1093
+/* "pywrapfst.pyx":1114
  * 
  * 
  * cpdef SymbolTable merge_symbol_table(_SymbolTable lhs, _SymbolTable rhs):             # <<<<<<<<<<<<<<
@@ -13859,14 +12886,14 @@ static PyObject *__pyx_pf_9pywrapfst_8compact_symbol_table(CYTHON_UNUSED PyObjec
  *   merge_symbol_table(lhs, rhs)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_11merge_symbol_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_13merge_symbol_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_merge_symbol_table(struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_lhs, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_rhs, CYTHON_UNUSED int __pyx_skip_dispatch) {
   struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("merge_symbol_table", 0);
 
-  /* "pywrapfst.pyx":1117
+  /* "pywrapfst.pyx":1138
  *   See also: `relabel_symbols`.
  *   """
  *   return _init_SymbolTable(fst.MergeSymbolTable(deref(lhs._table),             # <<<<<<<<<<<<<<
@@ -13876,10 +12903,10 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_merge_symbol_
   __Pyx_XDECREF(((PyObject *)__pyx_r));
   if (unlikely(((PyObject *)__pyx_v_lhs) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1117, __pyx_L1_error)
+    __PYX_ERR(0, 1138, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":1118
+  /* "pywrapfst.pyx":1139
  *   """
  *   return _init_SymbolTable(fst.MergeSymbolTable(deref(lhs._table),
  *                                                 deref(rhs._table), NULL))             # <<<<<<<<<<<<<<
@@ -13888,23 +12915,23 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_merge_symbol_
  */
   if (unlikely(((PyObject *)__pyx_v_rhs) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1118, __pyx_L1_error)
+    __PYX_ERR(0, 1139, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":1117
+  /* "pywrapfst.pyx":1138
  *   See also: `relabel_symbols`.
  *   """
  *   return _init_SymbolTable(fst.MergeSymbolTable(deref(lhs._table),             # <<<<<<<<<<<<<<
  *                                                 deref(rhs._table), NULL))
  * 
  */
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(fst::MergeSymbolTable((*__pyx_v_lhs->_table), (*__pyx_v_rhs->_table), NULL))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1117, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_SymbolTable(fst::MergeSymbolTable((*__pyx_v_lhs->_table), (*__pyx_v_rhs->_table), NULL))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1138, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst_SymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1093
+  /* "pywrapfst.pyx":1114
  * 
  * 
  * cpdef SymbolTable merge_symbol_table(_SymbolTable lhs, _SymbolTable rhs):             # <<<<<<<<<<<<<<
@@ -13924,9 +12951,9 @@ static struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_f_9pywrapfst_merge_symbol_
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_11merge_symbol_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_10merge_symbol_table[] = "\n  merge_symbol_table(lhs, rhs)\n\n  Merges all symbols from the left table into the right.\n\n  This function creates a new SymbolTable which is the merger of the two input\n  symbol Tables. Symbols in the right-hand table that conflict with those in the\n  left-hand table will be assigned values from the left-hand table. Thus the\n  returned table will never modify symbol assignments from the left-hand side,\n  but may do so on the right.\n\n  If the left-hand table is associated with an FST, it may be necessary to\n  relabel it using the output table.\n\n  Args:\n    lhs: Left-hand side SymbolTable.\n    rhs: Left-hand side SymbolTable.\n\n  Returns:\n    A new merged SymbolTable.\n\n  See also: `relabel_symbols`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_11merge_symbol_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_13merge_symbol_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_12merge_symbol_table[] = "\n  merge_symbol_table(lhs, rhs)\n\n  Merges all symbols from the left table into the right.\n\n  This function creates a new SymbolTable which is the merger of the two input\n  symbol Tables. Symbols in the right-hand table that conflict with those in the\n  left-hand table will be assigned values from the left-hand table. Thus the\n  returned table will never modify symbol assignments from the left-hand side,\n  but may do so on the right.\n\n  If the left-hand table is associated with an FST, it may be necessary to\n  relabel it using the output table.\n\n  Args:\n    lhs: Left-hand side SymbolTable.\n    rhs: Left-hand side SymbolTable.\n\n  Returns:\n    A new merged SymbolTable.\n\n  See also: `relabel_symbols`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_13merge_symbol_table(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_lhs = 0;
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_rhs = 0;
   PyObject *__pyx_r = 0;
@@ -13955,11 +12982,11 @@ static PyObject *__pyx_pw_9pywrapfst_11merge_symbol_table(PyObject *__pyx_self,
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rhs)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("merge_symbol_table", 1, 2, 2, 1); __PYX_ERR(0, 1093, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("merge_symbol_table", 1, 2, 2, 1); __PYX_ERR(0, 1114, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "merge_symbol_table") < 0)) __PYX_ERR(0, 1093, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "merge_symbol_table") < 0)) __PYX_ERR(0, 1114, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -13972,15 +12999,15 @@ static PyObject *__pyx_pw_9pywrapfst_11merge_symbol_table(PyObject *__pyx_self,
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("merge_symbol_table", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1093, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("merge_symbol_table", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1114, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.merge_symbol_table", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lhs), __pyx_ptype_9pywrapfst__SymbolTable, 1, "lhs", 0))) __PYX_ERR(0, 1093, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_rhs), __pyx_ptype_9pywrapfst__SymbolTable, 1, "rhs", 0))) __PYX_ERR(0, 1093, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_10merge_symbol_table(__pyx_self, __pyx_v_lhs, __pyx_v_rhs);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_lhs), __pyx_ptype_9pywrapfst__SymbolTable, 1, "lhs", 0))) __PYX_ERR(0, 1114, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_rhs), __pyx_ptype_9pywrapfst__SymbolTable, 1, "rhs", 0))) __PYX_ERR(0, 1114, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_12merge_symbol_table(__pyx_self, __pyx_v_lhs, __pyx_v_rhs);
 
   /* function exit code */
   goto __pyx_L0;
@@ -13991,13 +13018,13 @@ static PyObject *__pyx_pw_9pywrapfst_11merge_symbol_table(PyObject *__pyx_self,
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_10merge_symbol_table(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_lhs, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_rhs) {
+static PyObject *__pyx_pf_9pywrapfst_12merge_symbol_table(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_lhs, struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_rhs) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("merge_symbol_table", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_merge_symbol_table(__pyx_v_lhs, __pyx_v_rhs, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1093, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_merge_symbol_table(__pyx_v_lhs, __pyx_v_rhs, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1114, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -14014,7 +13041,7 @@ static PyObject *__pyx_pf_9pywrapfst_10merge_symbol_table(CYTHON_UNUSED PyObject
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1132
+/* "pywrapfst.pyx":1153
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -14042,10 +13069,9 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator___repr__(struct __pyx
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":1133
+  /* "pywrapfst.pyx":1154
  * 
  *   def __repr__(self):
  *     return "<SymbolTableIterator at 0x{:x}>".format(id(self))             # <<<<<<<<<<<<<<
@@ -14053,9 +13079,9 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator___repr__(struct __pyx
  *   def __init__(self, _SymbolTable syms):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_SymbolTableIterator_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1133, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_SymbolTableIterator_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1154, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1133, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1154, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
@@ -14067,47 +13093,17 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator___repr__(struct __pyx
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1133, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1133, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1133, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1133, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1133, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1154, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1132
+  /* "pywrapfst.pyx":1153
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -14121,7 +13117,6 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator___repr__(struct __pyx
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst.SymbolTableIterator.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -14130,7 +13125,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator___repr__(struct __pyx
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1135
+/* "pywrapfst.pyx":1156
  *     return "<SymbolTableIterator at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, _SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -14164,7 +13159,7 @@ static int __pyx_pw_9pywrapfst_19SymbolTableIterator_3__init__(PyObject *__pyx_v
         else goto __pyx_L5_argtuple_error;
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 1135, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 1156, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
       goto __pyx_L5_argtuple_error;
@@ -14175,13 +13170,13 @@ static int __pyx_pw_9pywrapfst_19SymbolTableIterator_3__init__(PyObject *__pyx_v
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1135, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1156, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.SymbolTableIterator.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 1135, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 1156, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_19SymbolTableIterator_2__init__(((struct __pyx_obj_9pywrapfst_SymbolTableIterator *)__pyx_v_self), __pyx_v_syms);
 
   /* function exit code */
@@ -14198,7 +13193,7 @@ static int __pyx_pf_9pywrapfst_19SymbolTableIterator_2__init__(struct __pyx_obj_
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":1136
+  /* "pywrapfst.pyx":1157
  * 
  *   def __init__(self, _SymbolTable syms):
  *     self._siter.reset(new fst.SymbolTableIterator(deref(syms._table)))             # <<<<<<<<<<<<<<
@@ -14207,15 +13202,15 @@ static int __pyx_pf_9pywrapfst_19SymbolTableIterator_2__init__(struct __pyx_obj_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 1136, __pyx_L1_error)
+    __PYX_ERR(0, 1157, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_syms) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1136, __pyx_L1_error)
+    __PYX_ERR(0, 1157, __pyx_L1_error)
   }
   __pyx_v_self->_siter.reset(new fst::SymbolTableIterator((*__pyx_v_syms->_table)));
 
-  /* "pywrapfst.pyx":1135
+  /* "pywrapfst.pyx":1156
  *     return "<SymbolTableIterator at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, _SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -14234,7 +13229,7 @@ static int __pyx_pf_9pywrapfst_19SymbolTableIterator_2__init__(struct __pyx_obj_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1139
+/* "pywrapfst.pyx":1160
  * 
  *   # This just registers this class as a possible iterator.
  *   def __iter__(self):             # <<<<<<<<<<<<<<
@@ -14260,7 +13255,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_4__iter__(struct __py
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__iter__", 0);
 
-  /* "pywrapfst.pyx":1140
+  /* "pywrapfst.pyx":1161
  *   # This just registers this class as a possible iterator.
  *   def __iter__(self):
  *     return self             # <<<<<<<<<<<<<<
@@ -14272,7 +13267,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_4__iter__(struct __py
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1139
+  /* "pywrapfst.pyx":1160
  * 
  *   # This just registers this class as a possible iterator.
  *   def __iter__(self):             # <<<<<<<<<<<<<<
@@ -14287,7 +13282,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_4__iter__(struct __py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1143
+/* "pywrapfst.pyx":1164
  * 
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):             # <<<<<<<<<<<<<<
@@ -14319,7 +13314,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
   PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("__next__", 0);
 
-  /* "pywrapfst.pyx":1144
+  /* "pywrapfst.pyx":1165
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):
  *     if self.done():             # <<<<<<<<<<<<<<
@@ -14328,12 +13323,12 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "done");
-    __PYX_ERR(0, 1144, __pyx_L1_error)
+    __PYX_ERR(0, 1165, __pyx_L1_error)
   }
   __pyx_t_1 = (((struct __pyx_vtabstruct_9pywrapfst_SymbolTableIterator *)__pyx_v_self->__pyx_vtab)->done(__pyx_v_self, 0) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":1145
+    /* "pywrapfst.pyx":1166
  *   def __next__(self):
  *     if self.done():
  *       raise StopIteration             # <<<<<<<<<<<<<<
@@ -14341,9 +13336,9 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
  *     cdef string symbol = self.symbol()
  */
     __Pyx_Raise(__pyx_builtin_StopIteration, 0, 0, 0);
-    __PYX_ERR(0, 1145, __pyx_L1_error)
+    __PYX_ERR(0, 1166, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1144
+    /* "pywrapfst.pyx":1165
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):
  *     if self.done():             # <<<<<<<<<<<<<<
@@ -14352,7 +13347,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
  */
   }
 
-  /* "pywrapfst.pyx":1146
+  /* "pywrapfst.pyx":1167
  *     if self.done():
  *       raise StopIteration
  *     cdef int64 value = self.value()             # <<<<<<<<<<<<<<
@@ -14361,11 +13356,11 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "value");
-    __PYX_ERR(0, 1146, __pyx_L1_error)
+    __PYX_ERR(0, 1167, __pyx_L1_error)
   }
   __pyx_v_value = ((struct __pyx_vtabstruct_9pywrapfst_SymbolTableIterator *)__pyx_v_self->__pyx_vtab)->value(__pyx_v_self, 0);
 
-  /* "pywrapfst.pyx":1147
+  /* "pywrapfst.pyx":1168
  *       raise StopIteration
  *     cdef int64 value = self.value()
  *     cdef string symbol = self.symbol()             # <<<<<<<<<<<<<<
@@ -14374,11 +13369,11 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "symbol");
-    __PYX_ERR(0, 1147, __pyx_L1_error)
+    __PYX_ERR(0, 1168, __pyx_L1_error)
   }
   __pyx_v_symbol = ((struct __pyx_vtabstruct_9pywrapfst_SymbolTableIterator *)__pyx_v_self->__pyx_vtab)->symbol(__pyx_v_self, 0);
 
-  /* "pywrapfst.pyx":1148
+  /* "pywrapfst.pyx":1169
  *     cdef int64 value = self.value()
  *     cdef string symbol = self.symbol()
  *     self.next()             # <<<<<<<<<<<<<<
@@ -14387,11 +13382,11 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "next");
-    __PYX_ERR(0, 1148, __pyx_L1_error)
+    __PYX_ERR(0, 1169, __pyx_L1_error)
   }
   ((struct __pyx_vtabstruct_9pywrapfst_SymbolTableIterator *)__pyx_v_self->__pyx_vtab)->next(__pyx_v_self, 0);
 
-  /* "pywrapfst.pyx":1149
+  /* "pywrapfst.pyx":1170
  *     cdef string symbol = self.symbol()
  *     self.next()
  *     return (value, symbol)             # <<<<<<<<<<<<<<
@@ -14399,11 +13394,11 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
  *   cpdef bool done(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_v_value); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1149, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_v_value); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1170, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_symbol); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1149, __pyx_L1_error)
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_symbol); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1170, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1149, __pyx_L1_error)
+  __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1170, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_2);
   PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
@@ -14415,7 +13410,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
   __pyx_t_4 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1143
+  /* "pywrapfst.pyx":1164
  * 
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):             # <<<<<<<<<<<<<<
@@ -14436,7 +13431,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_6__next__(struct __py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1151
+/* "pywrapfst.pyx":1172
  *     return (value, symbol)
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -14457,39 +13452,52 @@ static bool __pyx_f_9pywrapfst_19SymbolTableIterator_done(struct __pyx_obj_9pywr
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1151, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_19SymbolTableIterator_9done)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1172, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_19SymbolTableIterator_9done)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1172, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1172, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1151, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1151, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1151, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1160
+  /* "pywrapfst.pyx":1181
  *       True if the iterator is exhausted, False otherwise.
  *     """
  *     return self._siter.get().Done()             # <<<<<<<<<<<<<<
@@ -14498,12 +13506,12 @@ static bool __pyx_f_9pywrapfst_19SymbolTableIterator_done(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 1160, __pyx_L1_error)
+    __PYX_ERR(0, 1181, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_siter.get()->Done();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1151
+  /* "pywrapfst.pyx":1172
  *     return (value, symbol)
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -14544,7 +13552,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_8done(struct __pyx_ob
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("done", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_19SymbolTableIterator_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1151, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_19SymbolTableIterator_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1172, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -14561,7 +13569,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_8done(struct __pyx_ob
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1162
+/* "pywrapfst.pyx":1183
  *     return self._siter.get().Done()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -14580,37 +13588,50 @@ static void __pyx_f_9pywrapfst_19SymbolTableIterator_next(struct __pyx_obj_9pywr
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1162, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_19SymbolTableIterator_11next)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1183, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_19SymbolTableIterator_11next)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1183, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1162, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1162, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1168
+  /* "pywrapfst.pyx":1189
  *     Advances the iterator.
  *     """
  *     self._siter.get().Next()             # <<<<<<<<<<<<<<
@@ -14619,11 +13640,11 @@ static void __pyx_f_9pywrapfst_19SymbolTableIterator_next(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 1168, __pyx_L1_error)
+    __PYX_ERR(0, 1189, __pyx_L1_error)
   }
   __pyx_v_self->_siter.get()->Next();
 
-  /* "pywrapfst.pyx":1162
+  /* "pywrapfst.pyx":1183
  *     return self._siter.get().Done()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -14663,7 +13684,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_10next(struct __pyx_o
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("next", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_19SymbolTableIterator_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1162, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_19SymbolTableIterator_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1183, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -14680,7 +13701,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_10next(struct __pyx_o
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1170
+/* "pywrapfst.pyx":1191
  *     self._siter.get().Next()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -14699,37 +13720,50 @@ static void __pyx_f_9pywrapfst_19SymbolTableIterator_reset(struct __pyx_obj_9pyw
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1170, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_19SymbolTableIterator_13reset)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1191, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_19SymbolTableIterator_13reset)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1191, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1170, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1170, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1176
+  /* "pywrapfst.pyx":1197
  *     Resets the iterator to the initial position.
  *     """
  *     self._siter.get().Reset()             # <<<<<<<<<<<<<<
@@ -14738,11 +13772,11 @@ static void __pyx_f_9pywrapfst_19SymbolTableIterator_reset(struct __pyx_obj_9pyw
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 1176, __pyx_L1_error)
+    __PYX_ERR(0, 1197, __pyx_L1_error)
   }
   __pyx_v_self->_siter.get()->Reset();
 
-  /* "pywrapfst.pyx":1170
+  /* "pywrapfst.pyx":1191
  *     self._siter.get().Next()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -14782,7 +13816,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_12reset(struct __pyx_
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("reset", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_19SymbolTableIterator_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1170, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_19SymbolTableIterator_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1191, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -14799,7 +13833,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_12reset(struct __pyx_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1178
+/* "pywrapfst.pyx":1199
  *     self._siter.get().Reset()
  * 
  *   cpdef string symbol(self):             # <<<<<<<<<<<<<<
@@ -14820,39 +13854,52 @@ static std::string __pyx_f_9pywrapfst_19SymbolTableIterator_symbol(struct __pyx_
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_symbol); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1178, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_19SymbolTableIterator_15symbol)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_symbol); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1199, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_19SymbolTableIterator_15symbol)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1199, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1199, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1178, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1178, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1178, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1189
+  /* "pywrapfst.pyx":1210
  *       A symbol string.
  *     """
  *     return self._siter.get().Symbol()             # <<<<<<<<<<<<<<
@@ -14861,12 +13908,12 @@ static std::string __pyx_f_9pywrapfst_19SymbolTableIterator_symbol(struct __pyx_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 1189, __pyx_L1_error)
+    __PYX_ERR(0, 1210, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_siter.get()->Symbol();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1178
+  /* "pywrapfst.pyx":1199
  *     self._siter.get().Reset()
  * 
  *   cpdef string symbol(self):             # <<<<<<<<<<<<<<
@@ -14907,7 +13954,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_14symbol(struct __pyx
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("symbol", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_19SymbolTableIterator_symbol(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1178, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_19SymbolTableIterator_symbol(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1199, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -14924,7 +13971,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_14symbol(struct __pyx
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1191
+/* "pywrapfst.pyx":1212
  *     return self._siter.get().Symbol()
  * 
  *   cpdef int64 value(self):             # <<<<<<<<<<<<<<
@@ -14945,39 +13992,52 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_19SymbolTableIterator_value
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1191, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_19SymbolTableIterator_17value)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1212, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_19SymbolTableIterator_17value)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1212, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1212, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1191, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1191, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1191, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1200
+  /* "pywrapfst.pyx":1221
  *       An integer index.
  *     """
  *     return self._siter.get().Value()             # <<<<<<<<<<<<<<
@@ -14986,12 +14046,12 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_19SymbolTableIterator_value
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 1200, __pyx_L1_error)
+    __PYX_ERR(0, 1221, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_siter.get()->Value();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1191
+  /* "pywrapfst.pyx":1212
  *     return self._siter.get().Symbol()
  * 
  *   cpdef int64 value(self):             # <<<<<<<<<<<<<<
@@ -15032,7 +14092,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_16value(struct __pyx_
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("value", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_19SymbolTableIterator_value(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1191, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_19SymbolTableIterator_value(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1212, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -15080,7 +14140,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_18__reduce_cython__(C
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._siter,self._table cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__20, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -15133,7 +14193,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_20__setstate_cython__
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._siter,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__21, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -15156,7 +14216,7 @@ static PyObject *__pyx_pf_9pywrapfst_19SymbolTableIterator_20__setstate_cython__
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1229
+/* "pywrapfst.pyx":1250
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -15184,10 +14244,9 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper___repr__(struct __pyx_obj_9p
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":1230
+  /* "pywrapfst.pyx":1251
  * 
  *   def __repr__(self):
  *     return "<EncodeMapper at 0x{:x}>".format(id(self))             # <<<<<<<<<<<<<<
@@ -15195,9 +14254,9 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper___repr__(struct __pyx_obj_9p
  *   def __init__(self,
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_EncodeMapper_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1230, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_EncodeMapper_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1251, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1230, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1251, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
@@ -15209,47 +14268,17 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper___repr__(struct __pyx_obj_9p
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1230, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1230, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1230, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1230, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1230, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1251, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1229
+  /* "pywrapfst.pyx":1250
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -15263,7 +14292,6 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper___repr__(struct __pyx_obj_9p
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst.EncodeMapper.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -15272,7 +14300,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper___repr__(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1232
+/* "pywrapfst.pyx":1253
  *     return "<EncodeMapper at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self,             # <<<<<<<<<<<<<<
@@ -15327,7 +14355,7 @@ static int __pyx_pw_9pywrapfst_12EncodeMapper_3__init__(PyObject *__pyx_v_self,
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 1232, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 1253, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -15343,10 +14371,10 @@ static int __pyx_pw_9pywrapfst_12EncodeMapper_3__init__(PyObject *__pyx_v_self,
     }
     __pyx_v_arc_type = values[0];
     if (values[1]) {
-      __pyx_v_encode_labels = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_encode_labels == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1234, __pyx_L3_error)
+      __pyx_v_encode_labels = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_encode_labels == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1255, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":1234
+      /* "pywrapfst.pyx":1255
  *   def __init__(self,
  *                arc_type=b"standard",
  *                bool encode_labels=False,             # <<<<<<<<<<<<<<
@@ -15356,10 +14384,10 @@ static int __pyx_pw_9pywrapfst_12EncodeMapper_3__init__(PyObject *__pyx_v_self,
       __pyx_v_encode_labels = ((bool)0);
     }
     if (values[2]) {
-      __pyx_v_encode_weights = __Pyx_PyObject_IsTrue(values[2]); if (unlikely((__pyx_v_encode_weights == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1235, __pyx_L3_error)
+      __pyx_v_encode_weights = __Pyx_PyObject_IsTrue(values[2]); if (unlikely((__pyx_v_encode_weights == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1256, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":1235
+      /* "pywrapfst.pyx":1256
  *                arc_type=b"standard",
  *                bool encode_labels=False,
  *                bool encode_weights=False):             # <<<<<<<<<<<<<<
@@ -15371,7 +14399,7 @@ static int __pyx_pw_9pywrapfst_12EncodeMapper_3__init__(PyObject *__pyx_v_self,
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 0, 0, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1232, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__init__", 0, 0, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1253, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.EncodeMapper.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -15379,7 +14407,7 @@ static int __pyx_pw_9pywrapfst_12EncodeMapper_3__init__(PyObject *__pyx_v_self,
   __pyx_L4_argument_unpacking_done:;
   __pyx_r = __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(((struct __pyx_obj_9pywrapfst_EncodeMapper *)__pyx_v_self), __pyx_v_arc_type, __pyx_v_encode_labels, __pyx_v_encode_weights);
 
-  /* "pywrapfst.pyx":1232
+  /* "pywrapfst.pyx":1253
  *     return "<EncodeMapper at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self,             # <<<<<<<<<<<<<<
@@ -15403,10 +14431,9 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":1236
+  /* "pywrapfst.pyx":1257
  *                bool encode_labels=False,
  *                bool encode_weights=False):
  *     cdef uint32 flags = fst.GetEncodeFlags(encode_labels, encode_weights)             # <<<<<<<<<<<<<<
@@ -15415,7 +14442,7 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
  */
   __pyx_v_flags = fst::script::GetEncodeFlags(__pyx_v_encode_labels, __pyx_v_encode_weights);
 
-  /* "pywrapfst.pyx":1237
+  /* "pywrapfst.pyx":1258
  *                bool encode_weights=False):
  *     cdef uint32 flags = fst.GetEncodeFlags(encode_labels, encode_weights)
  *     self._encoder.reset(new fst.EncodeMapperClass(tostring(arc_type), flags,             # <<<<<<<<<<<<<<
@@ -15424,11 +14451,11 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1237, __pyx_L1_error)
+    __PYX_ERR(0, 1258, __pyx_L1_error)
   }
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_arc_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1237, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_arc_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1258, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1238
+  /* "pywrapfst.pyx":1259
  *     cdef uint32 flags = fst.GetEncodeFlags(encode_labels, encode_weights)
  *     self._encoder.reset(new fst.EncodeMapperClass(tostring(arc_type), flags,
  *                                                   fst.ENCODE))             # <<<<<<<<<<<<<<
@@ -15437,7 +14464,7 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
  */
   __pyx_v_self->_encoder.reset(new fst::script::EncodeMapperClass(__pyx_t_1, __pyx_v_flags, fst::ENCODE));
 
-  /* "pywrapfst.pyx":1239
+  /* "pywrapfst.pyx":1260
  *     self._encoder.reset(new fst.EncodeMapperClass(tostring(arc_type), flags,
  *                                                   fst.ENCODE))
  *     if not self._encoder:             # <<<<<<<<<<<<<<
@@ -15446,21 +14473,21 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1239, __pyx_L1_error)
+    __PYX_ERR(0, 1260, __pyx_L1_error)
   }
   __pyx_t_2 = ((!__pyx_v_self->_encoder) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":1240
+    /* "pywrapfst.pyx":1261
  *                                                   fst.ENCODE))
  *     if not self._encoder:
  *       raise FstOpError("Unknown arc type: {!r}".format(arc_type))             # <<<<<<<<<<<<<<
  * 
  *   cpdef string arc_type(self):
  */
-    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1240, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1261, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_arc_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1240, __pyx_L1_error)
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_arc_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1261, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
@@ -15472,38 +14499,10 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
         __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_arc_type); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1240, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_arc_type};
-        __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1240, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_arc_type};
-        __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1240, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1240, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_INCREF(__pyx_v_arc_type);
-        __Pyx_GIVEREF(__pyx_v_arc_type);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_arc_type);
-        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1240, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_v_arc_type) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_arc_type);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1261, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
@@ -15515,47 +14514,17 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
         __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1240, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1240, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1240, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1240, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_5);
-        __pyx_t_5 = 0;
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1240, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1261, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 1240, __pyx_L1_error)
+    __PYX_ERR(0, 1261, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1239
+    /* "pywrapfst.pyx":1260
  *     self._encoder.reset(new fst.EncodeMapperClass(tostring(arc_type), flags,
  *                                                   fst.ENCODE))
  *     if not self._encoder:             # <<<<<<<<<<<<<<
@@ -15564,7 +14533,7 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
  */
   }
 
-  /* "pywrapfst.pyx":1232
+  /* "pywrapfst.pyx":1253
  *     return "<EncodeMapper at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self,             # <<<<<<<<<<<<<<
@@ -15581,7 +14550,6 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst.EncodeMapper.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = -1;
   __pyx_L0:;
@@ -15589,7 +14557,7 @@ static int __pyx_pf_9pywrapfst_12EncodeMapper_2__init__(struct __pyx_obj_9pywrap
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1242
+/* "pywrapfst.pyx":1263
  *       raise FstOpError("Unknown arc type: {!r}".format(arc_type))
  * 
  *   cpdef string arc_type(self):             # <<<<<<<<<<<<<<
@@ -15610,39 +14578,52 @@ static std::string __pyx_f_9pywrapfst_12EncodeMapper_arc_type(struct __pyx_obj_9
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1242, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12EncodeMapper_5arc_type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1263, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12EncodeMapper_5arc_type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1263, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1263, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1242, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1242, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1242, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1248
+  /* "pywrapfst.pyx":1269
  *     Returns a string indicating the arc type.
  *     """
  *     return self._encoder.get().ArcType()             # <<<<<<<<<<<<<<
@@ -15651,12 +14632,12 @@ static std::string __pyx_f_9pywrapfst_12EncodeMapper_arc_type(struct __pyx_obj_9
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1248, __pyx_L1_error)
+    __PYX_ERR(0, 1269, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_encoder.get()->ArcType();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1242
+  /* "pywrapfst.pyx":1263
  *       raise FstOpError("Unknown arc type: {!r}".format(arc_type))
  * 
  *   cpdef string arc_type(self):             # <<<<<<<<<<<<<<
@@ -15697,7 +14678,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_4arc_type(struct __pyx_obj_9
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("arc_type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_12EncodeMapper_arc_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1242, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_12EncodeMapper_arc_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1263, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -15714,7 +14695,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_4arc_type(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1252
+/* "pywrapfst.pyx":1273
  *   # Python's equivalent to operator().
  * 
  *   def __call__(self, Arc arc):             # <<<<<<<<<<<<<<
@@ -15752,7 +14733,7 @@ static PyObject *__pyx_pw_9pywrapfst_12EncodeMapper_7__call__(PyObject *__pyx_v_
         else goto __pyx_L5_argtuple_error;
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__call__") < 0)) __PYX_ERR(0, 1252, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__call__") < 0)) __PYX_ERR(0, 1273, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
       goto __pyx_L5_argtuple_error;
@@ -15763,13 +14744,13 @@ static PyObject *__pyx_pw_9pywrapfst_12EncodeMapper_7__call__(PyObject *__pyx_v_
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__call__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1252, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__call__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1273, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.EncodeMapper.__call__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_arc), __pyx_ptype_9pywrapfst_Arc, 1, "arc", 0))) __PYX_ERR(0, 1252, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_arc), __pyx_ptype_9pywrapfst_Arc, 1, "arc", 0))) __PYX_ERR(0, 1273, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_12EncodeMapper_6__call__(((struct __pyx_obj_9pywrapfst_EncodeMapper *)__pyx_v_self), __pyx_v_arc);
 
   /* function exit code */
@@ -15787,7 +14768,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_6__call__(struct __pyx_obj_9
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__call__", 0);
 
-  /* "pywrapfst.pyx":1268
+  /* "pywrapfst.pyx":1289
  *       FstOpError: Incompatible or invalid weight.
  *     """
  *     return _init_Arc(self._encoder.get().__call__(deref(arc._arc)))             # <<<<<<<<<<<<<<
@@ -15797,19 +14778,19 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_6__call__(struct __pyx_obj_9
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1268, __pyx_L1_error)
+    __PYX_ERR(0, 1289, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_arc) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 1268, __pyx_L1_error)
+    __PYX_ERR(0, 1289, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_Arc(__pyx_v_self->_encoder.get()->operator()((*__pyx_v_arc->_arc)))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1268, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_Arc(__pyx_v_self->_encoder.get()->operator()((*__pyx_v_arc->_arc)))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1289, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1252
+  /* "pywrapfst.pyx":1273
  *   # Python's equivalent to operator().
  * 
  *   def __call__(self, Arc arc):             # <<<<<<<<<<<<<<
@@ -15828,7 +14809,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_6__call__(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1270
+/* "pywrapfst.pyx":1291
  *     return _init_Arc(self._encoder.get().__call__(deref(arc._arc)))
  * 
  *   cpdef uint32 flags(self):             # <<<<<<<<<<<<<<
@@ -15849,39 +14830,52 @@ static __pyx_t_10basictypes_uint32 __pyx_f_9pywrapfst_12EncodeMapper_flags(struc
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1270, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12EncodeMapper_9flags)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1291, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12EncodeMapper_9flags)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1291, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_uint32_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1291, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1270, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1270, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_uint32_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1270, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1276
+  /* "pywrapfst.pyx":1297
  *     Returns the encoder's flags.
  *     """
  *     return self._encoder.get().Flags()             # <<<<<<<<<<<<<<
@@ -15890,12 +14884,12 @@ static __pyx_t_10basictypes_uint32 __pyx_f_9pywrapfst_12EncodeMapper_flags(struc
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1276, __pyx_L1_error)
+    __PYX_ERR(0, 1297, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_encoder.get()->Flags();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1270
+  /* "pywrapfst.pyx":1291
  *     return _init_Arc(self._encoder.get().__call__(deref(arc._arc)))
  * 
  *   cpdef uint32 flags(self):             # <<<<<<<<<<<<<<
@@ -15936,7 +14930,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_8flags(struct __pyx_obj_9pyw
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("flags", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(__pyx_f_9pywrapfst_12EncodeMapper_flags(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1270, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(__pyx_f_9pywrapfst_12EncodeMapper_flags(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1291, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -15953,7 +14947,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_8flags(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1278
+/* "pywrapfst.pyx":1299
  *     return self._encoder.get().Flags()
  * 
  *   cpdef _EncodeMapperSymbolTable input_symbols(self):             # <<<<<<<<<<<<<<
@@ -15975,40 +14969,53 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_input_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1278, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12EncodeMapper_11input_symbols)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_input_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1299, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12EncodeMapper_11input_symbols)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1299, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__EncodeMapperSymbolTable))))) __PYX_ERR(0, 1299, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1278, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1278, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__EncodeMapperSymbolTable))))) __PYX_ERR(0, 1278, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1285
+  /* "pywrapfst.pyx":1306
  *     """
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *         self._encoder.get().InputSymbols())             # <<<<<<<<<<<<<<
@@ -16017,10 +15024,10 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1285, __pyx_L1_error)
+    __PYX_ERR(0, 1306, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":1284
+  /* "pywrapfst.pyx":1305
  *     Returns the encoder's input symbol table, or None if none is present.
  *     """
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](             # <<<<<<<<<<<<<<
@@ -16029,7 +15036,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
  */
   __pyx_v_syms = const_cast<__pyx_t_9pywrapfst_SymbolTable_ptr>(__pyx_v_self->_encoder.get()->InputSymbols());
 
-  /* "pywrapfst.pyx":1286
+  /* "pywrapfst.pyx":1307
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *         self._encoder.get().InputSymbols())
  *     if syms == NULL:             # <<<<<<<<<<<<<<
@@ -16039,7 +15046,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
   __pyx_t_5 = ((__pyx_v_syms == NULL) != 0);
   if (__pyx_t_5) {
 
-    /* "pywrapfst.pyx":1287
+    /* "pywrapfst.pyx":1308
  *         self._encoder.get().InputSymbols())
  *     if syms == NULL:
  *       return             # <<<<<<<<<<<<<<
@@ -16050,7 +15057,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
     __pyx_r = ((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)Py_None); __Pyx_INCREF(Py_None);
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":1286
+    /* "pywrapfst.pyx":1307
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *         self._encoder.get().InputSymbols())
  *     if syms == NULL:             # <<<<<<<<<<<<<<
@@ -16059,7 +15066,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
  */
   }
 
-  /* "pywrapfst.pyx":1288
+  /* "pywrapfst.pyx":1309
  *     if syms == NULL:
  *       return
  *     return _init_EncodeMapperSymbolTable(syms, self._encoder)             # <<<<<<<<<<<<<<
@@ -16069,15 +15076,15 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
   __Pyx_XDECREF(((PyObject *)__pyx_r));
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1288, __pyx_L1_error)
+    __PYX_ERR(0, 1309, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_EncodeMapperSymbolTable(__pyx_v_syms, __pyx_v_self->_encoder)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1288, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_EncodeMapperSymbolTable(__pyx_v_syms, __pyx_v_self->_encoder)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1309, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1278
+  /* "pywrapfst.pyx":1299
  *     return self._encoder.get().Flags()
  * 
  *   cpdef _EncodeMapperSymbolTable input_symbols(self):             # <<<<<<<<<<<<<<
@@ -16119,7 +15126,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_10input_symbols(struct __pyx
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("input_symbols", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_12EncodeMapper_input_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1278, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_12EncodeMapper_input_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1299, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -16136,7 +15143,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_10input_symbols(struct __pyx
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1290
+/* "pywrapfst.pyx":1311
  *     return _init_EncodeMapperSymbolTable(syms, self._encoder)
  * 
  *   cpdef _EncodeMapperSymbolTable output_symbols(self):             # <<<<<<<<<<<<<<
@@ -16158,40 +15165,53 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_output_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1290, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12EncodeMapper_13output_symbols)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_output_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1311, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12EncodeMapper_13output_symbols)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1311, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__EncodeMapperSymbolTable))))) __PYX_ERR(0, 1311, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1290, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1290, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__EncodeMapperSymbolTable))))) __PYX_ERR(0, 1290, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1297
+  /* "pywrapfst.pyx":1318
  *     """
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *         self._encoder.get().OutputSymbols())             # <<<<<<<<<<<<<<
@@ -16200,10 +15220,10 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1297, __pyx_L1_error)
+    __PYX_ERR(0, 1318, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":1296
+  /* "pywrapfst.pyx":1317
  *     Returns the encoder's output symbol table, or None if none is present.
  *     """
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](             # <<<<<<<<<<<<<<
@@ -16212,7 +15232,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
  */
   __pyx_v_syms = const_cast<__pyx_t_9pywrapfst_SymbolTable_ptr>(__pyx_v_self->_encoder.get()->OutputSymbols());
 
-  /* "pywrapfst.pyx":1298
+  /* "pywrapfst.pyx":1319
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *         self._encoder.get().OutputSymbols())
  *     if syms == NULL:             # <<<<<<<<<<<<<<
@@ -16222,7 +15242,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
   __pyx_t_5 = ((__pyx_v_syms == NULL) != 0);
   if (__pyx_t_5) {
 
-    /* "pywrapfst.pyx":1299
+    /* "pywrapfst.pyx":1320
  *         self._encoder.get().OutputSymbols())
  *     if syms == NULL:
  *       return             # <<<<<<<<<<<<<<
@@ -16233,7 +15253,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
     __pyx_r = ((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)Py_None); __Pyx_INCREF(Py_None);
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":1298
+    /* "pywrapfst.pyx":1319
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *         self._encoder.get().OutputSymbols())
  *     if syms == NULL:             # <<<<<<<<<<<<<<
@@ -16242,7 +15262,7 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
  */
   }
 
-  /* "pywrapfst.pyx":1300
+  /* "pywrapfst.pyx":1321
  *     if syms == NULL:
  *       return
  *     return _init_EncodeMapperSymbolTable(syms, self._encoder)             # <<<<<<<<<<<<<<
@@ -16252,15 +15272,15 @@ static struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *__pyx_f_9pywrapfst_
   __Pyx_XDECREF(((PyObject *)__pyx_r));
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1300, __pyx_L1_error)
+    __PYX_ERR(0, 1321, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_EncodeMapperSymbolTable(__pyx_v_syms, __pyx_v_self->_encoder)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1300, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_EncodeMapperSymbolTable(__pyx_v_syms, __pyx_v_self->_encoder)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1321, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__EncodeMapperSymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1290
+  /* "pywrapfst.pyx":1311
  *     return _init_EncodeMapperSymbolTable(syms, self._encoder)
  * 
  *   cpdef _EncodeMapperSymbolTable output_symbols(self):             # <<<<<<<<<<<<<<
@@ -16302,7 +15322,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_12output_symbols(struct __py
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("output_symbols", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_12EncodeMapper_output_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1290, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_12EncodeMapper_output_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1311, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -16319,7 +15339,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_12output_symbols(struct __py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1302
+/* "pywrapfst.pyx":1323
  *     return _init_EncodeMapperSymbolTable(syms, self._encoder)
  * 
  *   cpdef uint64 properties(self, uint64 mask):             # <<<<<<<<<<<<<<
@@ -16336,75 +15356,60 @@ static __pyx_t_10basictypes_uint64 __pyx_f_9pywrapfst_12EncodeMapper_properties(
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  __pyx_t_10basictypes_uint64 __pyx_t_7;
+  __pyx_t_10basictypes_uint64 __pyx_t_6;
   __Pyx_RefNannySetupContext("properties", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_properties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1302, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12EncodeMapper_15properties)) {
-      __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_mask); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1302, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_properties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1323, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12EncodeMapper_15properties)) {
+        __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_mask); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1323, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1302, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1323, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1302, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1302, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1302, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1302, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_6 = __Pyx_PyInt_As_uint64_t(__pyx_t_2); if (unlikely((__pyx_t_6 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1323, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_6;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_7 = __Pyx_PyInt_As_uint64_t(__pyx_t_2); if (unlikely((__pyx_t_7 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1302, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_7;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1316
+  /* "pywrapfst.pyx":1337
  *       A 64-bit bitmask representing the requested properties.
  *     """
  *     return self._encoder.get().Properties(mask)             # <<<<<<<<<<<<<<
@@ -16413,12 +15418,12 @@ static __pyx_t_10basictypes_uint64 __pyx_f_9pywrapfst_12EncodeMapper_properties(
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1316, __pyx_L1_error)
+    __PYX_ERR(0, 1337, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_encoder.get()->Properties(__pyx_v_mask);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1302
+  /* "pywrapfst.pyx":1323
  *     return _init_EncodeMapperSymbolTable(syms, self._encoder)
  * 
  *   cpdef uint64 properties(self, uint64 mask):             # <<<<<<<<<<<<<<
@@ -16433,7 +15438,6 @@ static __pyx_t_10basictypes_uint64 __pyx_f_9pywrapfst_12EncodeMapper_properties(
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_WriteUnraisable("pywrapfst.EncodeMapper.properties", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
   __pyx_r = 0;
   __pyx_L0:;
@@ -16450,7 +15454,7 @@ static PyObject *__pyx_pw_9pywrapfst_12EncodeMapper_15properties(PyObject *__pyx
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("properties (wrapper)", 0);
   assert(__pyx_arg_mask); {
-    __pyx_v_mask = __Pyx_PyInt_As_uint64_t(__pyx_arg_mask); if (unlikely((__pyx_v_mask == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1302, __pyx_L3_error)
+    __pyx_v_mask = __Pyx_PyInt_As_uint64_t(__pyx_arg_mask); if (unlikely((__pyx_v_mask == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1323, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -16471,7 +15475,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_14properties(struct __pyx_ob
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("properties", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(__pyx_f_9pywrapfst_12EncodeMapper_properties(__pyx_v_self, __pyx_v_mask, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1302, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(__pyx_f_9pywrapfst_12EncodeMapper_properties(__pyx_v_self, __pyx_v_mask, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1323, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -16488,7 +15492,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_14properties(struct __pyx_ob
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1318
+/* "pywrapfst.pyx":1339
  *     return self._encoder.get().Properties(mask)
  * 
  *   cpdef void set_input_symbols(self, _SymbolTable syms) except *:             # <<<<<<<<<<<<<<
@@ -16503,67 +15507,54 @@ static void __pyx_f_9pywrapfst_12EncodeMapper_set_input_symbols(struct __pyx_obj
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("set_input_symbols", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_input_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1318, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12EncodeMapper_17set_input_symbols)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_input_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1339, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12EncodeMapper_17set_input_symbols)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_syms)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1318, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, ((PyObject *)__pyx_v_syms)) : __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_syms));
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1339, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_syms)};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1318, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_syms)};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1318, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1318, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(((PyObject *)__pyx_v_syms));
-          __Pyx_GIVEREF(((PyObject *)__pyx_v_syms));
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, ((PyObject *)__pyx_v_syms));
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1318, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1329
+  /* "pywrapfst.pyx":1350
  *     See also: `set_output_symbols`.
  *     """
  *     self._encoder.get().SetInputSymbols(syms._table)             # <<<<<<<<<<<<<<
@@ -16572,15 +15563,15 @@ static void __pyx_f_9pywrapfst_12EncodeMapper_set_input_symbols(struct __pyx_obj
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1329, __pyx_L1_error)
+    __PYX_ERR(0, 1350, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_syms) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1329, __pyx_L1_error)
+    __PYX_ERR(0, 1350, __pyx_L1_error)
   }
   __pyx_v_self->_encoder.get()->SetInputSymbols(__pyx_v_syms->_table);
 
-  /* "pywrapfst.pyx":1318
+  /* "pywrapfst.pyx":1339
  *     return self._encoder.get().Properties(mask)
  * 
  *   cpdef void set_input_symbols(self, _SymbolTable syms) except *:             # <<<<<<<<<<<<<<
@@ -16595,7 +15586,6 @@ static void __pyx_f_9pywrapfst_12EncodeMapper_set_input_symbols(struct __pyx_obj
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst.EncodeMapper.set_input_symbols", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -16608,7 +15598,7 @@ static PyObject *__pyx_pw_9pywrapfst_12EncodeMapper_17set_input_symbols(PyObject
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_input_symbols (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 1318, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 1339, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_12EncodeMapper_16set_input_symbols(((struct __pyx_obj_9pywrapfst_EncodeMapper *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_syms));
 
   /* function exit code */
@@ -16626,8 +15616,8 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_16set_input_symbols(struct _
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("set_input_symbols", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_f_9pywrapfst_12EncodeMapper_set_input_symbols(__pyx_v_self, __pyx_v_syms, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1318, __pyx_L1_error)
-  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1318, __pyx_L1_error)
+  __pyx_f_9pywrapfst_12EncodeMapper_set_input_symbols(__pyx_v_self, __pyx_v_syms, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1339, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1339, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -16644,7 +15634,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_16set_input_symbols(struct _
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1331
+/* "pywrapfst.pyx":1352
  *     self._encoder.get().SetInputSymbols(syms._table)
  * 
  *   cpdef void set_output_symbols(self, _SymbolTable syms) except *:             # <<<<<<<<<<<<<<
@@ -16659,67 +15649,54 @@ static void __pyx_f_9pywrapfst_12EncodeMapper_set_output_symbols(struct __pyx_ob
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("set_output_symbols", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_output_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1331, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12EncodeMapper_19set_output_symbols)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_output_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1352, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12EncodeMapper_19set_output_symbols)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_syms)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1331, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, ((PyObject *)__pyx_v_syms)) : __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_syms));
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1352, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_syms)};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1331, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_syms)};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1331, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1331, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(((PyObject *)__pyx_v_syms));
-          __Pyx_GIVEREF(((PyObject *)__pyx_v_syms));
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, ((PyObject *)__pyx_v_syms));
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1331, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1342
+  /* "pywrapfst.pyx":1363
  *     See also: `set_input_symbols`.
  *     """
  *     self._encoder.get().SetOutputSymbols(syms._table)             # <<<<<<<<<<<<<<
@@ -16728,15 +15705,15 @@ static void __pyx_f_9pywrapfst_12EncodeMapper_set_output_symbols(struct __pyx_ob
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1342, __pyx_L1_error)
+    __PYX_ERR(0, 1363, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_syms) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 1342, __pyx_L1_error)
+    __PYX_ERR(0, 1363, __pyx_L1_error)
   }
   __pyx_v_self->_encoder.get()->SetOutputSymbols(__pyx_v_syms->_table);
 
-  /* "pywrapfst.pyx":1331
+  /* "pywrapfst.pyx":1352
  *     self._encoder.get().SetInputSymbols(syms._table)
  * 
  *   cpdef void set_output_symbols(self, _SymbolTable syms) except *:             # <<<<<<<<<<<<<<
@@ -16751,7 +15728,6 @@ static void __pyx_f_9pywrapfst_12EncodeMapper_set_output_symbols(struct __pyx_ob
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst.EncodeMapper.set_output_symbols", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -16764,7 +15740,7 @@ static PyObject *__pyx_pw_9pywrapfst_12EncodeMapper_19set_output_symbols(PyObjec
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_output_symbols (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 1331, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 1352, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_12EncodeMapper_18set_output_symbols(((struct __pyx_obj_9pywrapfst_EncodeMapper *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_syms));
 
   /* function exit code */
@@ -16782,8 +15758,8 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_18set_output_symbols(struct
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("set_output_symbols", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_f_9pywrapfst_12EncodeMapper_set_output_symbols(__pyx_v_self, __pyx_v_syms, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1331, __pyx_L1_error)
-  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1331, __pyx_L1_error)
+  __pyx_f_9pywrapfst_12EncodeMapper_set_output_symbols(__pyx_v_self, __pyx_v_syms, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1352, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1352, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -16800,7 +15776,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_18set_output_symbols(struct
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1344
+/* "pywrapfst.pyx":1365
  *     self._encoder.get().SetOutputSymbols(syms._table)
  * 
  *   cpdef string weight_type(self):             # <<<<<<<<<<<<<<
@@ -16821,39 +15797,52 @@ static std::string __pyx_f_9pywrapfst_12EncodeMapper_weight_type(struct __pyx_ob
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_weight_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1344, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_12EncodeMapper_21weight_type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_weight_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1365, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_12EncodeMapper_21weight_type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1365, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1365, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1344, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1344, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1344, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1350
+  /* "pywrapfst.pyx":1371
  *     Returns a string indicating the weight type.
  *     """
  *     return self._encoder.get().WeightType()             # <<<<<<<<<<<<<<
@@ -16862,12 +15851,12 @@ static std::string __pyx_f_9pywrapfst_12EncodeMapper_weight_type(struct __pyx_ob
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1350, __pyx_L1_error)
+    __PYX_ERR(0, 1371, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_encoder.get()->WeightType();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1344
+  /* "pywrapfst.pyx":1365
  *     self._encoder.get().SetOutputSymbols(syms._table)
  * 
  *   cpdef string weight_type(self):             # <<<<<<<<<<<<<<
@@ -16908,7 +15897,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_20weight_type(struct __pyx_o
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("weight_type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_12EncodeMapper_weight_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1344, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_12EncodeMapper_weight_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1365, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -16956,7 +15945,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_22__reduce_cython__(CYTHON_U
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._encoder cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__22, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -17009,7 +15998,7 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_24__setstate_cython__(CYTHON
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._encoder cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__23, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -17032,178 +16021,98 @@ static PyObject *__pyx_pf_9pywrapfst_12EncodeMapper_24__setstate_cython__(CYTHON
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1374
- * 
- *   # IPython notebook magic to produce an SVG of the FST.
- *   def _repr_svg_(self):             # <<<<<<<<<<<<<<
- *     """IPython notebook magic to produce an SVG of the FST using GraphViz.
+/* "pywrapfst.pyx":1397
  * 
+ *   @staticmethod
+ *   cdef string _local_render_svg(const string &dot):             # <<<<<<<<<<<<<<
+ *     proc = subprocess.Popen(("dot", "-Tsvg"),
+ *                             stdin=subprocess.PIPE,
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_4_Fst_1_repr_svg_(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9pywrapfst_4_Fst__repr_svg_[] = "IPython notebook magic to produce an SVG of the FST using GraphViz.\n\n    This method produces an SVG of the internal graph. Users wishing to create\n    publication-quality graphs should instead use the method `draw`, which\n    exposes additional parameters.\n\n    Raises:\n      OSError: Cannot locate the `dot` executable.\n      subprocess.CalledProcessError: `dot` returned non-zero exit code.\n\n    See also: `draw`, `text`.\n    ";
-static PyObject *__pyx_pw_9pywrapfst_4_Fst_1_repr_svg_(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_repr_svg_ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_4_Fst__repr_svg_(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_4_Fst__repr_svg_(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
+static std::string __pyx_f_9pywrapfst_4_Fst__local_render_svg(std::string const &__pyx_v_dot) {
   PyObject *__pyx_v_proc = NULL;
-  std::stringstream __pyx_v_sstrm;
-  PyObject *__pyx_v_sout = NULL;
-  CYTHON_UNUSED PyObject *__pyx_v_serr = NULL;
-  PyObject *__pyx_r = NULL;
+  std::string __pyx_r;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  PyObject *(*__pyx_t_6)(PyObject *);
-  int __pyx_t_7;
-  int __pyx_t_8;
-  PyObject *__pyx_t_9 = NULL;
-  __Pyx_RefNannySetupContext("_repr_svg_", 0);
+  std::string __pyx_t_5;
+  __Pyx_RefNannySetupContext("_local_render_svg", 0);
 
-  /* "pywrapfst.pyx":1388
- *     """
- *     # Throws OSError if the dot executable is not found.
- *     proc = subprocess.Popen(["dot", "-Tsvg"], stdin=subprocess.PIPE,             # <<<<<<<<<<<<<<
- *                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- *     cdef stringstream sstrm
+  /* "pywrapfst.pyx":1398
+ *   @staticmethod
+ *   cdef string _local_render_svg(const string &dot):
+ *     proc = subprocess.Popen(("dot", "-Tsvg"),             # <<<<<<<<<<<<<<
+ *                             stdin=subprocess.PIPE,
+ *                             stdout=subprocess.PIPE)
  */
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_subprocess); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1388, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_subprocess); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1398, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_Popen); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1388, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_Popen); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1398, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyList_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1388, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_n_s_dot);
-  __Pyx_GIVEREF(__pyx_n_s_dot);
-  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_dot);
-  __Pyx_INCREF(__pyx_kp_s_Tsvg);
-  __Pyx_GIVEREF(__pyx_kp_s_Tsvg);
-  PyList_SET_ITEM(__pyx_t_1, 1, __pyx_kp_s_Tsvg);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1388, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_GIVEREF(__pyx_t_1);
-  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
-  __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyDict_NewPresized(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1388, __pyx_L1_error)
+
+  /* "pywrapfst.pyx":1399
+ *   cdef string _local_render_svg(const string &dot):
+ *     proc = subprocess.Popen(("dot", "-Tsvg"),
+ *                             stdin=subprocess.PIPE,             # <<<<<<<<<<<<<<
+ *                             stdout=subprocess.PIPE)
+ *     return proc.communicate(dot.encode("utf8"))[0]
+ */
+  __pyx_t_1 = __Pyx_PyDict_NewPresized(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1399, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_subprocess); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1388, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_subprocess); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1399, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_PIPE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1399, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_PIPE); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1388, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_stdin, __pyx_t_4) < 0) __PYX_ERR(0, 1399, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_stdin, __pyx_t_5) < 0) __PYX_ERR(0, 1388, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-  /* "pywrapfst.pyx":1389
- *     # Throws OSError if the dot executable is not found.
- *     proc = subprocess.Popen(["dot", "-Tsvg"], stdin=subprocess.PIPE,
- *                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)             # <<<<<<<<<<<<<<
- *     cdef stringstream sstrm
- *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),
+  /* "pywrapfst.pyx":1400
+ *     proc = subprocess.Popen(("dot", "-Tsvg"),
+ *                             stdin=subprocess.PIPE,
+ *                             stdout=subprocess.PIPE)             # <<<<<<<<<<<<<<
+ *     return proc.communicate(dot.encode("utf8"))[0]
+ * 
  */
-  __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_subprocess); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1389, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_PIPE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1389, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_subprocess); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1400, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_stdout, __pyx_t_4) < 0) __PYX_ERR(0, 1388, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_subprocess); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1389, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_PIPE); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1389, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_PIPE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1400, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_stderr, __pyx_t_5) < 0) __PYX_ERR(0, 1388, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_stdout, __pyx_t_3) < 0) __PYX_ERR(0, 1399, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "pywrapfst.pyx":1388
- *     """
- *     # Throws OSError if the dot executable is not found.
- *     proc = subprocess.Popen(["dot", "-Tsvg"], stdin=subprocess.PIPE,             # <<<<<<<<<<<<<<
- *                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- *     cdef stringstream sstrm
+  /* "pywrapfst.pyx":1398
+ *   @staticmethod
+ *   cdef string _local_render_svg(const string &dot):
+ *     proc = subprocess.Popen(("dot", "-Tsvg"),             # <<<<<<<<<<<<<<
+ *                             stdin=subprocess.PIPE,
+ *                             stdout=subprocess.PIPE)
  */
-  __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1388, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__9, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1398, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_proc = __pyx_t_5;
-  __pyx_t_5 = 0;
-
-  /* "pywrapfst.pyx":1391
- *                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- *     cdef stringstream sstrm
- *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),             # <<<<<<<<<<<<<<
- *                 self._fst.get().OutputSymbols(), NULL,
- *                 self._fst.get().Properties(fst.kAcceptor, True) ==
- */
-  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1391, __pyx_L1_error)
-  }
-  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1391, __pyx_L1_error)
-  }
-
-  /* "pywrapfst.pyx":1392
- *     cdef stringstream sstrm
- *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),
- *                 self._fst.get().OutputSymbols(), NULL,             # <<<<<<<<<<<<<<
- *                 self._fst.get().Properties(fst.kAcceptor, True) ==
- *                 fst.kAcceptor,
- */
-  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1392, __pyx_L1_error)
-  }
-
-  /* "pywrapfst.pyx":1393
- *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),
- *                 self._fst.get().OutputSymbols(), NULL,
- *                 self._fst.get().Properties(fst.kAcceptor, True) ==             # <<<<<<<<<<<<<<
- *                 fst.kAcceptor,
- *                 b"", 8.5, 11, True, False, 0.4, 0.25, 14, 5, b"g", False,
- */
-  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1393, __pyx_L1_error)
-  }
-
-  /* "pywrapfst.pyx":1391
- *                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- *     cdef stringstream sstrm
- *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),             # <<<<<<<<<<<<<<
- *                 self._fst.get().OutputSymbols(), NULL,
- *                 self._fst.get().Properties(fst.kAcceptor, True) ==
- */
-  fst::script::DrawFst((*__pyx_v_self->_fst), __pyx_v_self->_fst.get()->InputSymbols(), __pyx_v_self->_fst.get()->OutputSymbols(), NULL, (__pyx_v_self->_fst.get()->Properties(fst::kAcceptor, 1) == fst::kAcceptor), __pyx_k__24, 8.5, 11.0, 1, 0, 0.4, 0.25, 14, 5, __pyx_k_g, 0, (&__pyx_v_sstrm), __pyx_k_repr_svg);
+  __pyx_v_proc = __pyx_t_3;
+  __pyx_t_3 = 0;
 
-  /* "pywrapfst.pyx":1397
- *                 b"", 8.5, 11, True, False, 0.4, 0.25, 14, 5, b"g", False,
- *                 addr(sstrm), b"_repr_svg")
- *     (sout, serr) = proc.communicate(sstrm.str())             # <<<<<<<<<<<<<<
- *     if proc.returncode != 0:  # Just to be explicit.
- *       raise subprocess.CalledProcessError(proc.returncode, self._DOT_TSVG)
+  /* "pywrapfst.pyx":1401
+ *                             stdin=subprocess.PIPE,
+ *                             stdout=subprocess.PIPE)
+ *     return proc.communicate(dot.encode("utf8"))[0]             # <<<<<<<<<<<<<<
+ * 
+ *   def _repr_svg_(self):
  */
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_proc, __pyx_n_s_communicate); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1397, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_proc, __pyx_n_s_communicate); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1401, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_sstrm.str()); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1397, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_2 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_dot); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1401, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyUnicode_AsUTF8String(((PyObject*)__pyx_t_2)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1401, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_t_2 = NULL;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) {
     __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
@@ -17214,209 +16123,30 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst__repr_svg_(struct __pyx_obj_9pywrapfs
       __Pyx_DECREF_SET(__pyx_t_1, function);
     }
   }
-  if (!__pyx_t_2) {
-    __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1397, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_5);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_1)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_t_3};
-      __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1397, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_t_3};
-      __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1397, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_4 = PyTuple_New(1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1397, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2); __pyx_t_2 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_4, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_4, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1397, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    }
-  }
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if ((likely(PyTuple_CheckExact(__pyx_t_5))) || (PyList_CheckExact(__pyx_t_5))) {
-    PyObject* sequence = __pyx_t_5;
-    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-    if (unlikely(size != 2)) {
-      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-      __PYX_ERR(0, 1397, __pyx_L1_error)
-    }
-    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-    if (likely(PyTuple_CheckExact(sequence))) {
-      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); 
-      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
-    } else {
-      __pyx_t_1 = PyList_GET_ITEM(sequence, 0); 
-      __pyx_t_4 = PyList_GET_ITEM(sequence, 1); 
-    }
-    __Pyx_INCREF(__pyx_t_1);
-    __Pyx_INCREF(__pyx_t_4);
-    #else
-    __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1397, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1397, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    #endif
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  } else {
-    Py_ssize_t index = -1;
-    __pyx_t_3 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1397, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_6 = Py_TYPE(__pyx_t_3)->tp_iternext;
-    index = 0; __pyx_t_1 = __pyx_t_6(__pyx_t_3); if (unlikely(!__pyx_t_1)) goto __pyx_L3_unpacking_failed;
-    __Pyx_GOTREF(__pyx_t_1);
-    index = 1; __pyx_t_4 = __pyx_t_6(__pyx_t_3); if (unlikely(!__pyx_t_4)) goto __pyx_L3_unpacking_failed;
-    __Pyx_GOTREF(__pyx_t_4);
-    if (__Pyx_IternextUnpackEndCheck(__pyx_t_6(__pyx_t_3), 2) < 0) __PYX_ERR(0, 1397, __pyx_L1_error)
-    __pyx_t_6 = NULL;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    goto __pyx_L4_unpacking_done;
-    __pyx_L3_unpacking_failed:;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_6 = NULL;
-    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-    __PYX_ERR(0, 1397, __pyx_L1_error)
-    __pyx_L4_unpacking_done:;
-  }
-  __pyx_v_sout = __pyx_t_1;
-  __pyx_t_1 = 0;
-  __pyx_v_serr = __pyx_t_4;
-  __pyx_t_4 = 0;
-
-  /* "pywrapfst.pyx":1398
- *                 addr(sstrm), b"_repr_svg")
- *     (sout, serr) = proc.communicate(sstrm.str())
- *     if proc.returncode != 0:  # Just to be explicit.             # <<<<<<<<<<<<<<
- *       raise subprocess.CalledProcessError(proc.returncode, self._DOT_TSVG)
- *     return sout.decode("utf8")
- */
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_proc, __pyx_n_s_returncode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1398, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_4 = PyObject_RichCompare(__pyx_t_5, __pyx_int_0, Py_NE); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1398, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 1398, __pyx_L1_error)
+  __pyx_t_3 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_2, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (unlikely(__pyx_t_7)) {
-
-    /* "pywrapfst.pyx":1399
- *     (sout, serr) = proc.communicate(sstrm.str())
- *     if proc.returncode != 0:  # Just to be explicit.
- *       raise subprocess.CalledProcessError(proc.returncode, self._DOT_TSVG)             # <<<<<<<<<<<<<<
- *     return sout.decode("utf8")
- * 
- */
-    __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_subprocess); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1399, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_CalledProcessError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1399, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_proc, __pyx_n_s_returncode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1399, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_DOT_TSVG); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1399, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = NULL;
-    __pyx_t_8 = 0;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
-      __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
-      if (likely(__pyx_t_2)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
-        __Pyx_INCREF(__pyx_t_2);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_1, function);
-        __pyx_t_8 = 1;
-      }
-    }
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_1)) {
-      PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_t_5, __pyx_t_3};
-      __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1399, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) {
-      PyObject *__pyx_temp[3] = {__pyx_t_2, __pyx_t_5, __pyx_t_3};
-      __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1399, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1399, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      if (__pyx_t_2) {
-        __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_2); __pyx_t_2 = NULL;
-      }
-      __Pyx_GIVEREF(__pyx_t_5);
-      PyTuple_SET_ITEM(__pyx_t_9, 0+__pyx_t_8, __pyx_t_5);
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_9, 1+__pyx_t_8, __pyx_t_3);
-      __pyx_t_5 = 0;
-      __pyx_t_3 = 0;
-      __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_9, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1399, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-    }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __PYX_ERR(0, 1399, __pyx_L1_error)
-
-    /* "pywrapfst.pyx":1398
- *                 addr(sstrm), b"_repr_svg")
- *     (sout, serr) = proc.communicate(sstrm.str())
- *     if proc.returncode != 0:  # Just to be explicit.             # <<<<<<<<<<<<<<
- *       raise subprocess.CalledProcessError(proc.returncode, self._DOT_TSVG)
- *     return sout.decode("utf8")
- */
+  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1401, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (unlikely(__pyx_t_3 == Py_None)) {
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
+    __PYX_ERR(0, 1401, __pyx_L1_error)
   }
-
-  /* "pywrapfst.pyx":1400
- *     if proc.returncode != 0:  # Just to be explicit.
- *       raise subprocess.CalledProcessError(proc.returncode, self._DOT_TSVG)
- *     return sout.decode("utf8")             # <<<<<<<<<<<<<<
- * 
- *   def __repr__(self):
- */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_sout, __pyx_n_s_decode); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1400, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_tuple__25, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1400, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_3, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1401, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1401, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_r = __pyx_t_5;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1374
- * 
- *   # IPython notebook magic to produce an SVG of the FST.
- *   def _repr_svg_(self):             # <<<<<<<<<<<<<<
- *     """IPython notebook magic to produce an SVG of the FST using GraphViz.
+  /* "pywrapfst.pyx":1397
  * 
+ *   @staticmethod
+ *   cdef string _local_render_svg(const string &dot):             # <<<<<<<<<<<<<<
+ *     proc = subprocess.Popen(("dot", "-Tsvg"),
+ *                             stdin=subprocess.PIPE,
  */
 
   /* function exit code */
@@ -17425,149 +16155,330 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst__repr_svg_(struct __pyx_obj_9pywrapfs
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_AddTraceback("pywrapfst._Fst._repr_svg_", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+  __Pyx_WriteUnraisable("pywrapfst._Fst._local_render_svg", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
+  __Pyx_pretend_to_initialize(&__pyx_r);
   __pyx_L0:;
   __Pyx_XDECREF(__pyx_v_proc);
-  __Pyx_XDECREF(__pyx_v_sout);
-  __Pyx_XDECREF(__pyx_v_serr);
-  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1402
- *     return sout.decode("utf8")
+/* "pywrapfst.pyx":1403
+ *     return proc.communicate(dot.encode("utf8"))[0]
  * 
- *   def __repr__(self):             # <<<<<<<<<<<<<<
- *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+ *   def _repr_svg_(self):             # <<<<<<<<<<<<<<
+ *     """IPython notebook magic to produce an SVG of the FST using GraphViz.
  * 
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_4_Fst_3__repr__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_4_Fst_3__repr__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pw_9pywrapfst_4_Fst_1_repr_svg_(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9pywrapfst_4_Fst__repr_svg_[] = "IPython notebook magic to produce an SVG of the FST using GraphViz.\n\n    This method produces an SVG of the internal graph. Users wishing to create\n    publication-quality graphs should instead use the method `draw`, which\n    exposes additional parameters.\n\n    See also: `draw`, `text`.\n    ";
+static PyObject *__pyx_pw_9pywrapfst_4_Fst_1_repr_svg_(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_4_Fst_2__repr__(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("_repr_svg_ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9pywrapfst_4_Fst__repr_svg_(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_4_Fst_2__repr__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
+static PyObject *__pyx_pf_9pywrapfst_4_Fst__repr_svg_(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
+  std::stringstream __pyx_v_sstrm;
+  bool __pyx_v_acceptor;
+  PyObject *__pyx_v_e = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  int __pyx_t_6;
+  int __pyx_t_5;
+  PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  __Pyx_RefNannySetupContext("__repr__", 0);
+  PyObject *__pyx_t_8 = NULL;
+  PyObject *__pyx_t_9 = NULL;
+  PyObject *__pyx_t_10 = NULL;
+  PyObject *__pyx_t_11 = NULL;
+  int __pyx_t_12;
+  char const *__pyx_t_13;
+  PyObject *__pyx_t_14 = NULL;
+  PyObject *__pyx_t_15 = NULL;
+  PyObject *__pyx_t_16 = NULL;
+  PyObject *__pyx_t_17 = NULL;
+  PyObject *__pyx_t_18 = NULL;
+  PyObject *__pyx_t_19 = NULL;
+  __Pyx_RefNannySetupContext("_repr_svg_", 0);
 
-  /* "pywrapfst.pyx":1403
- * 
- *   def __repr__(self):
- *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))             # <<<<<<<<<<<<<<
- * 
- *   def __init__(self):
+  /* "pywrapfst.pyx":1413
+ *     """
+ *     cdef stringstream sstrm
+ *     cdef bool acceptor = (self._fst.get().Properties(fst.kAcceptor, True) ==             # <<<<<<<<<<<<<<
+ *                           fst.kAcceptor)
+ *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Fst_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1403, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "fst_type");
-    __PYX_ERR(0, 1403, __pyx_L1_error)
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
+    __PYX_ERR(0, 1413, __pyx_L1_error)
   }
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_self->__pyx_vtab)->fst_type(__pyx_v_self, 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1403, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1403, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = NULL;
-  __pyx_t_6 = 0;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_5)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_5);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-      __pyx_t_6 = 1;
-    }
+
+  /* "pywrapfst.pyx":1414
+ *     cdef stringstream sstrm
+ *     cdef bool acceptor = (self._fst.get().Properties(fst.kAcceptor, True) ==
+ *                           fst.kAcceptor)             # <<<<<<<<<<<<<<
+ *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),
+ *                 self._fst.get().OutputSymbols(), NULL, acceptor,
+ */
+  __pyx_v_acceptor = (__pyx_v_self->_fst.get()->Properties(fst::kAcceptor, 1) == fst::kAcceptor);
+
+  /* "pywrapfst.pyx":1415
+ *     cdef bool acceptor = (self._fst.get().Properties(fst.kAcceptor, True) ==
+ *                           fst.kAcceptor)
+ *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),             # <<<<<<<<<<<<<<
+ *                 self._fst.get().OutputSymbols(), NULL, acceptor,
+ *                 b"", 8.5, 11, True, False, 0.4, 0.25, 14, 5, b"g", False,
+ */
+  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
+    __PYX_ERR(0, 1415, __pyx_L1_error)
   }
-  #if CYTHON_FAST_PYCALL
-  if (PyFunction_Check(__pyx_t_2)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1403, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  } else
-  #endif
-  #if CYTHON_FAST_PYCCALL
-  if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1403, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  } else
-  #endif
+  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
+    __PYX_ERR(0, 1415, __pyx_L1_error)
+  }
+
+  /* "pywrapfst.pyx":1416
+ *                           fst.kAcceptor)
+ *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),
+ *                 self._fst.get().OutputSymbols(), NULL, acceptor,             # <<<<<<<<<<<<<<
+ *                 b"", 8.5, 11, True, False, 0.4, 0.25, 14, 5, b"g", False,
+ *                 addr(sstrm), b"<pywrapfst>")
+ */
+  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
+    __PYX_ERR(0, 1416, __pyx_L1_error)
+  }
+
+  /* "pywrapfst.pyx":1415
+ *     cdef bool acceptor = (self._fst.get().Properties(fst.kAcceptor, True) ==
+ *                           fst.kAcceptor)
+ *     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),             # <<<<<<<<<<<<<<
+ *                 self._fst.get().OutputSymbols(), NULL, acceptor,
+ *                 b"", 8.5, 11, True, False, 0.4, 0.25, 14, 5, b"g", False,
+ */
+  fst::script::DrawFst((*__pyx_v_self->_fst), __pyx_v_self->_fst.get()->InputSymbols(), __pyx_v_self->_fst.get()->OutputSymbols(), NULL, __pyx_v_acceptor, __pyx_k__10, 8.5, 11.0, 1, 0, 0.4, 0.25, 14, 5, __pyx_k_g, 0, (&__pyx_v_sstrm), __pyx_k_pywrapfst);
+
+  /* "pywrapfst.pyx":1419
+ *                 b"", 8.5, 11, True, False, 0.4, 0.25, 14, 5, b"g", False,
+ *                 addr(sstrm), b"<pywrapfst>")
+ *     try:             # <<<<<<<<<<<<<<
+ *       return _Fst._local_render_svg(sstrm.str())
+ *     except Exception as e:
+ */
   {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1403, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
+    __Pyx_PyThreadState_declare
+    __Pyx_PyThreadState_assign
+    __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3);
+    __Pyx_XGOTREF(__pyx_t_1);
+    __Pyx_XGOTREF(__pyx_t_2);
+    __Pyx_XGOTREF(__pyx_t_3);
+    /*try:*/ {
+
+      /* "pywrapfst.pyx":1420
+ *                 addr(sstrm), b"<pywrapfst>")
+ *     try:
+ *       return _Fst._local_render_svg(sstrm.str())             # <<<<<<<<<<<<<<
+ *     except Exception as e:
+ *       logging.warning("Dot rendering failed: " + str(e))
+ */
+      __Pyx_XDECREF(__pyx_r);
+      __pyx_t_4 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_4_Fst__local_render_svg(__pyx_v_sstrm.str())); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1420, __pyx_L3_error)
+      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_r = __pyx_t_4;
+      __pyx_t_4 = 0;
+      goto __pyx_L7_try_return;
+
+      /* "pywrapfst.pyx":1419
+ *                 b"", 8.5, 11, True, False, 0.4, 0.25, 14, 5, b"g", False,
+ *                 addr(sstrm), b"<pywrapfst>")
+ *     try:             # <<<<<<<<<<<<<<
+ *       return _Fst._local_render_svg(sstrm.str())
+ *     except Exception as e:
+ */
+    }
+    __pyx_L3_error:;
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+
+    /* "pywrapfst.pyx":1421
+ *     try:
+ *       return _Fst._local_render_svg(sstrm.str())
+ *     except Exception as e:             # <<<<<<<<<<<<<<
+ *       logging.warning("Dot rendering failed: " + str(e))
+ * 
+ */
+    __pyx_t_5 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0])));
     if (__pyx_t_5) {
-      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
+      __Pyx_AddTraceback("pywrapfst._Fst._repr_svg_", __pyx_clineno, __pyx_lineno, __pyx_filename);
+      if (__Pyx_GetException(&__pyx_t_4, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 1421, __pyx_L5_except_error)
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_GOTREF(__pyx_t_6);
+      __Pyx_GOTREF(__pyx_t_7);
+      __Pyx_INCREF(__pyx_t_6);
+      __pyx_v_e = __pyx_t_6;
+      /*try:*/ {
+
+        /* "pywrapfst.pyx":1422
+ *       return _Fst._local_render_svg(sstrm.str())
+ *     except Exception as e:
+ *       logging.warning("Dot rendering failed: " + str(e))             # <<<<<<<<<<<<<<
+ * 
+ *   def __init__(self):
+ */
+        __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_logging); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1422, __pyx_L14_error)
+        __Pyx_GOTREF(__pyx_t_9);
+        __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_warning); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1422, __pyx_L14_error)
+        __Pyx_GOTREF(__pyx_t_10);
+        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+        __pyx_t_9 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyUnicode_Type)), __pyx_v_e); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1422, __pyx_L14_error)
+        __Pyx_GOTREF(__pyx_t_9);
+        __pyx_t_11 = __Pyx_PyUnicode_Concat(__pyx_kp_u_Dot_rendering_failed, __pyx_t_9); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1422, __pyx_L14_error)
+        __Pyx_GOTREF(__pyx_t_11);
+        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+        __pyx_t_9 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_10))) {
+          __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_10);
+          if (likely(__pyx_t_9)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10);
+            __Pyx_INCREF(__pyx_t_9);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_10, function);
+          }
+        }
+        __pyx_t_8 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_10, __pyx_t_9, __pyx_t_11) : __Pyx_PyObject_CallOneArg(__pyx_t_10, __pyx_t_11);
+        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
+        __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+        if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1422, __pyx_L14_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      }
+
+      /* "pywrapfst.pyx":1421
+ *     try:
+ *       return _Fst._local_render_svg(sstrm.str())
+ *     except Exception as e:             # <<<<<<<<<<<<<<
+ *       logging.warning("Dot rendering failed: " + str(e))
+ * 
+ */
+      /*finally:*/ {
+        /*normal exit:*/{
+          __Pyx_DECREF(__pyx_v_e);
+          __pyx_v_e = NULL;
+          goto __pyx_L15;
+        }
+        __pyx_L14_error:;
+        /*exception exit:*/{
+          __Pyx_PyThreadState_declare
+          __Pyx_PyThreadState_assign
+          __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; __pyx_t_18 = 0; __pyx_t_19 = 0;
+          __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
+          __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
+          __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
+          __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+          if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_17, &__pyx_t_18, &__pyx_t_19);
+          if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16) < 0)) __Pyx_ErrFetch(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16);
+          __Pyx_XGOTREF(__pyx_t_14);
+          __Pyx_XGOTREF(__pyx_t_15);
+          __Pyx_XGOTREF(__pyx_t_16);
+          __Pyx_XGOTREF(__pyx_t_17);
+          __Pyx_XGOTREF(__pyx_t_18);
+          __Pyx_XGOTREF(__pyx_t_19);
+          __pyx_t_5 = __pyx_lineno; __pyx_t_12 = __pyx_clineno; __pyx_t_13 = __pyx_filename;
+          {
+            __Pyx_DECREF(__pyx_v_e);
+            __pyx_v_e = NULL;
+          }
+          if (PY_MAJOR_VERSION >= 3) {
+            __Pyx_XGIVEREF(__pyx_t_17);
+            __Pyx_XGIVEREF(__pyx_t_18);
+            __Pyx_XGIVEREF(__pyx_t_19);
+            __Pyx_ExceptionReset(__pyx_t_17, __pyx_t_18, __pyx_t_19);
+          }
+          __Pyx_XGIVEREF(__pyx_t_14);
+          __Pyx_XGIVEREF(__pyx_t_15);
+          __Pyx_XGIVEREF(__pyx_t_16);
+          __Pyx_ErrRestore(__pyx_t_14, __pyx_t_15, __pyx_t_16);
+          __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; __pyx_t_18 = 0; __pyx_t_19 = 0;
+          __pyx_lineno = __pyx_t_5; __pyx_clineno = __pyx_t_12; __pyx_filename = __pyx_t_13;
+          goto __pyx_L5_except_error;
+        }
+        __pyx_L15:;
+      }
+      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+      goto __pyx_L4_exception_handled;
     }
-    __Pyx_GIVEREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_4);
-    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_4);
-    __pyx_t_3 = 0;
-    __pyx_t_4 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1403, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    goto __pyx_L5_except_error;
+    __pyx_L5_except_error:;
+
+    /* "pywrapfst.pyx":1419
+ *                 b"", 8.5, 11, True, False, 0.4, 0.25, 14, 5, b"g", False,
+ *                 addr(sstrm), b"<pywrapfst>")
+ *     try:             # <<<<<<<<<<<<<<
+ *       return _Fst._local_render_svg(sstrm.str())
+ *     except Exception as e:
+ */
+    __Pyx_XGIVEREF(__pyx_t_1);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
+    goto __pyx_L1_error;
+    __pyx_L7_try_return:;
+    __Pyx_XGIVEREF(__pyx_t_1);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
+    goto __pyx_L0;
+    __pyx_L4_exception_handled:;
+    __Pyx_XGIVEREF(__pyx_t_1);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
   }
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1402
- *     return sout.decode("utf8")
+  /* "pywrapfst.pyx":1403
+ *     return proc.communicate(dot.encode("utf8"))[0]
  * 
- *   def __repr__(self):             # <<<<<<<<<<<<<<
- *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+ *   def _repr_svg_(self):             # <<<<<<<<<<<<<<
+ *     """IPython notebook magic to produce an SVG of the FST using GraphViz.
  * 
  */
 
   /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_AddTraceback("pywrapfst._Fst.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_XDECREF(__pyx_t_9);
+  __Pyx_XDECREF(__pyx_t_10);
+  __Pyx_XDECREF(__pyx_t_11);
+  __Pyx_AddTraceback("pywrapfst._Fst._repr_svg_", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_e);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1405
- *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+/* "pywrapfst.pyx":1424
+ *       logging.warning("Dot rendering failed: " + str(e))
  * 
  *   def __init__(self):             # <<<<<<<<<<<<<<
  *     raise FstDeletedConstructorError(
@@ -17575,22 +16486,22 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_2__repr__(struct __pyx_obj_9pywrapfst
  */
 
 /* Python wrapper */
-static int __pyx_pw_9pywrapfst_4_Fst_5__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pw_9pywrapfst_4_Fst_5__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static int __pyx_pw_9pywrapfst_4_Fst_3__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_9pywrapfst_4_Fst_3__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
   if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) {
     __Pyx_RaiseArgtupleInvalid("__init__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;}
   if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__init__", 0))) return -1;
-  __pyx_r = __pyx_pf_9pywrapfst_4_Fst_4__init__(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9pywrapfst_4_Fst_2__init__(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9pywrapfst_4_Fst_4__init__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
+static int __pyx_pf_9pywrapfst_4_Fst_2__init__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -17599,31 +16510,30 @@ static int __pyx_pf_9pywrapfst_4_Fst_4__init__(struct __pyx_obj_9pywrapfst__Fst
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
-  PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":1406
+  /* "pywrapfst.pyx":1425
  * 
  *   def __init__(self):
  *     raise FstDeletedConstructorError(             # <<<<<<<<<<<<<<
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstDeletedConstructorError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1406, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstDeletedConstructorError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1425, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
 
-  /* "pywrapfst.pyx":1407
+  /* "pywrapfst.pyx":1426
  *   def __init__(self):
  *     raise FstDeletedConstructorError(
  *         "Cannot construct {}".format(self.__class__.__name__))             # <<<<<<<<<<<<<<
  * 
- *   def __str__(self):
+ *   # Registers the class for pickling; must be repeated in any subclass which
  */
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Cannot_construct, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1407, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Cannot_construct, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1426, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_class); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1407, __pyx_L1_error)
+  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_class); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1426, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1407, __pyx_L1_error)
+  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1426, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __pyx_t_5 = NULL;
@@ -17636,41 +16546,11 @@ static int __pyx_pf_9pywrapfst_4_Fst_4__init__(struct __pyx_obj_9pywrapfst__Fst
       __Pyx_DECREF_SET(__pyx_t_4, function);
     }
   }
-  if (!__pyx_t_5) {
-    __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1407, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_GOTREF(__pyx_t_3);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_6};
-      __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1407, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_6};
-      __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1407, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1407, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
-      __Pyx_GIVEREF(__pyx_t_6);
-      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_t_6);
-      __pyx_t_6 = 0;
-      __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1407, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    }
-  }
+  __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1426, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
@@ -17682,48 +16562,18 @@ static int __pyx_pf_9pywrapfst_4_Fst_4__init__(struct __pyx_obj_9pywrapfst__Fst
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1406, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1406, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1406, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1406, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1406, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1425, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(0, 1406, __pyx_L1_error)
+  __PYX_ERR(0, 1425, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1405
- *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+  /* "pywrapfst.pyx":1424
+ *       logging.warning("Dot rendering failed: " + str(e))
  * 
  *   def __init__(self):             # <<<<<<<<<<<<<<
  *     raise FstDeletedConstructorError(
@@ -17738,99 +16588,34 @@ static int __pyx_pf_9pywrapfst_4_Fst_4__init__(struct __pyx_obj_9pywrapfst__Fst
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_AddTraceback("pywrapfst._Fst.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = -1;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1409
- *         "Cannot construct {}".format(self.__class__.__name__))
- * 
- *   def __str__(self):             # <<<<<<<<<<<<<<
- *     return self.text()
- * 
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_4_Fst_7__str__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_4_Fst_7__str__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__str__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_4_Fst_6__str__(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_4_Fst_6__str__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("__str__", 0);
-
-  /* "pywrapfst.pyx":1410
- * 
- *   def __str__(self):
- *     return self.text()             # <<<<<<<<<<<<<<
- * 
- *   # Registers the class for pickling; must be repeated in any subclass which
- */
-  __Pyx_XDECREF(__pyx_r);
-  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "text");
-    __PYX_ERR(0, 1410, __pyx_L1_error)
-  }
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_self->__pyx_vtab)->text(__pyx_v_self, 0, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1410, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
-  /* "pywrapfst.pyx":1409
- *         "Cannot construct {}".format(self.__class__.__name__))
- * 
- *   def __str__(self):             # <<<<<<<<<<<<<<
- *     return self.text()
- * 
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._Fst.__str__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "pywrapfst.pyx":1415
+/* "pywrapfst.pyx":1431
  *   # can't be derived by _init_XFst.
  * 
  *   def __reduce__(self):             # <<<<<<<<<<<<<<
- *     return (_read_from_string, (self.write_to_string(),))
+ *     return (_read_Fst_from_string, (self.write_to_string(),))
  * 
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_4_Fst_9__reduce__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_4_Fst_9__reduce__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9pywrapfst_4_Fst_5__reduce__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_4_Fst_5__reduce__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__reduce__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_4_Fst_8__reduce__(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9pywrapfst_4_Fst_4__reduce__(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_4_Fst_8__reduce__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
+static PyObject *__pyx_pf_9pywrapfst_4_Fst_4__reduce__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -17838,28 +16623,28 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_8__reduce__(struct __pyx_obj_9pywrapf
   PyObject *__pyx_t_3 = NULL;
   __Pyx_RefNannySetupContext("__reduce__", 0);
 
-  /* "pywrapfst.pyx":1416
+  /* "pywrapfst.pyx":1432
  * 
  *   def __reduce__(self):
- *     return (_read_from_string, (self.write_to_string(),))             # <<<<<<<<<<<<<<
+ *     return (_read_Fst_from_string, (self.write_to_string(),))             # <<<<<<<<<<<<<<
  * 
- *   cpdef string arc_type(self):
+ *   def __repr__(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_read_from_string); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1416, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_read_Fst_from_string); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1432, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "write_to_string");
-    __PYX_ERR(0, 1416, __pyx_L1_error)
+    __PYX_ERR(0, 1432, __pyx_L1_error)
   }
-  __pyx_t_2 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_self->__pyx_vtab)->write_to_string(__pyx_v_self, 0)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1416, __pyx_L1_error)
+  __pyx_t_2 = ((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_self->__pyx_vtab)->write_to_string(__pyx_v_self, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1432, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1416, __pyx_L1_error)
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1432, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_GIVEREF(__pyx_t_2);
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);
   __pyx_t_2 = 0;
-  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1416, __pyx_L1_error)
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1432, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
@@ -17871,11 +16656,11 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_8__reduce__(struct __pyx_obj_9pywrapf
   __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1415
+  /* "pywrapfst.pyx":1431
  *   # can't be derived by _init_XFst.
  * 
  *   def __reduce__(self):             # <<<<<<<<<<<<<<
- *     return (_read_from_string, (self.write_to_string(),))
+ *     return (_read_Fst_from_string, (self.write_to_string(),))
  * 
  */
 
@@ -17892,8 +16677,200 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_8__reduce__(struct __pyx_obj_9pywrapf
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1418
- *     return (_read_from_string, (self.write_to_string(),))
+/* "pywrapfst.pyx":1434
+ *     return (_read_Fst_from_string, (self.write_to_string(),))
+ * 
+ *   def __repr__(self):             # <<<<<<<<<<<<<<
+ *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+ * 
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9pywrapfst_4_Fst_7__repr__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_4_Fst_7__repr__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9pywrapfst_4_Fst_6__repr__(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9pywrapfst_4_Fst_6__repr__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
+  __Pyx_RefNannySetupContext("__repr__", 0);
+
+  /* "pywrapfst.pyx":1435
+ * 
+ *   def __repr__(self):
+ *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))             # <<<<<<<<<<<<<<
+ * 
+ *   def __str__(self):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Fst_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1435, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "fst_type");
+    __PYX_ERR(0, 1435, __pyx_L1_error)
+  }
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_self->__pyx_vtab)->fst_type(__pyx_v_self, 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1435, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1435, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = NULL;
+  __pyx_t_6 = 0;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+      __pyx_t_6 = 1;
+    }
+  }
+  #if CYTHON_FAST_PYCALL
+  if (PyFunction_Check(__pyx_t_2)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1435, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  } else
+  #endif
+  #if CYTHON_FAST_PYCCALL
+  if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1435, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  } else
+  #endif
+  {
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1435, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    if (__pyx_t_5) {
+      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
+    }
+    __Pyx_GIVEREF(__pyx_t_3);
+    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_4);
+    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_4);
+    __pyx_t_3 = 0;
+    __pyx_t_4 = 0;
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1435, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+  }
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "pywrapfst.pyx":1434
+ *     return (_read_Fst_from_string, (self.write_to_string(),))
+ * 
+ *   def __repr__(self):             # <<<<<<<<<<<<<<
+ *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+ * 
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("pywrapfst._Fst.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pywrapfst.pyx":1437
+ *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+ * 
+ *   def __str__(self):             # <<<<<<<<<<<<<<
+ *     return self.text()
+ * 
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9pywrapfst_4_Fst_9__str__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_4_Fst_9__str__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__str__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9pywrapfst_4_Fst_8__str__(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9pywrapfst_4_Fst_8__str__(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  __Pyx_RefNannySetupContext("__str__", 0);
+
+  /* "pywrapfst.pyx":1438
+ * 
+ *   def __str__(self):
+ *     return self.text()             # <<<<<<<<<<<<<<
+ * 
+ *   cpdef string arc_type(self):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "text");
+    __PYX_ERR(0, 1438, __pyx_L1_error)
+  }
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_self->__pyx_vtab)->text(__pyx_v_self, 0, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1438, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "pywrapfst.pyx":1437
+ *     return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+ * 
+ *   def __str__(self):             # <<<<<<<<<<<<<<
+ *     return self.text()
+ * 
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pywrapfst._Fst.__str__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pywrapfst.pyx":1440
+ *     return self.text()
  * 
  *   cpdef string arc_type(self):             # <<<<<<<<<<<<<<
  *     """
@@ -17913,39 +16890,52 @@ static std::string __pyx_f_9pywrapfst_4_Fst_arc_type(struct __pyx_obj_9pywrapfst
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1418, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_11arc_type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1440, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_11arc_type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1440, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1440, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1418, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1418, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1418, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1424
+  /* "pywrapfst.pyx":1446
  *     Returns a string indicating the arc type.
  *     """
  *     return self._fst.get().ArcType()             # <<<<<<<<<<<<<<
@@ -17954,13 +16944,13 @@ static std::string __pyx_f_9pywrapfst_4_Fst_arc_type(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1424, __pyx_L1_error)
+    __PYX_ERR(0, 1446, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_fst.get()->ArcType();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1418
- *     return (_read_from_string, (self.write_to_string(),))
+  /* "pywrapfst.pyx":1440
+ *     return self.text()
  * 
  *   cpdef string arc_type(self):             # <<<<<<<<<<<<<<
  *     """
@@ -18000,7 +16990,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_10arc_type(struct __pyx_obj_9pywrapfs
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("arc_type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_4_Fst_arc_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1418, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_4_Fst_arc_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1440, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -18017,7 +17007,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_10arc_type(struct __pyx_obj_9pywrapfs
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1426
+/* "pywrapfst.pyx":1448
  *     return self._fst.get().ArcType()
  * 
  *   cpdef ArcIterator arcs(self, int64 state):             # <<<<<<<<<<<<<<
@@ -18034,75 +17024,60 @@ static struct __pyx_obj_9pywrapfst_ArcIterator *__pyx_f_9pywrapfst_4_Fst_arcs(st
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
   __Pyx_RefNannySetupContext("arcs", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arcs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1426, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_13arcs)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1426, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arcs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1448, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_13arcs)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1448, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1426, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1448, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1426, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1426, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1426, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1426, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_ArcIterator))))) __PYX_ERR(0, 1448, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst_ArcIterator *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_ArcIterator))))) __PYX_ERR(0, 1426, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst_ArcIterator *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1440
+  /* "pywrapfst.pyx":1462
  *     See also: `mutable_arcs`, `states`.
  *     """
  *     return ArcIterator(self, state)             # <<<<<<<<<<<<<<
@@ -18110,9 +17085,9 @@ static struct __pyx_obj_9pywrapfst_ArcIterator *__pyx_f_9pywrapfst_4_Fst_arcs(st
  *   cpdef _Fst copy(self):
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1440, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1462, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1440, __pyx_L1_error)
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1462, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_INCREF(((PyObject *)__pyx_v_self));
   __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
@@ -18120,14 +17095,14 @@ static struct __pyx_obj_9pywrapfst_ArcIterator *__pyx_f_9pywrapfst_4_Fst_arcs(st
   __Pyx_GIVEREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_ArcIterator), __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1440, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_ArcIterator), __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1462, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_r = ((struct __pyx_obj_9pywrapfst_ArcIterator *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1426
+  /* "pywrapfst.pyx":1448
  *     return self._fst.get().ArcType()
  * 
  *   cpdef ArcIterator arcs(self, int64 state):             # <<<<<<<<<<<<<<
@@ -18142,7 +17117,6 @@ static struct __pyx_obj_9pywrapfst_ArcIterator *__pyx_f_9pywrapfst_4_Fst_arcs(st
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_AddTraceback("pywrapfst._Fst.arcs", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -18160,7 +17134,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_13arcs(PyObject *__pyx_v_self, PyObje
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("arcs (wrapper)", 0);
   assert(__pyx_arg_state); {
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1426, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1448, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -18181,7 +17155,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_12arcs(struct __pyx_obj_9pywrapfst__F
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("arcs", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_arcs(__pyx_v_self, __pyx_v_state, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1426, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_arcs(__pyx_v_self, __pyx_v_state, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1448, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -18198,7 +17172,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_12arcs(struct __pyx_obj_9pywrapfst__F
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1442
+/* "pywrapfst.pyx":1464
  *     return ArcIterator(self, state)
  * 
  *   cpdef _Fst copy(self):             # <<<<<<<<<<<<<<
@@ -18218,40 +17192,53 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_4_Fst_copy(struct __
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_copy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1442, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_15copy)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_copy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1464, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_15copy)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1464, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 1464, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1442, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1442, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 1442, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1448
+  /* "pywrapfst.pyx":1470
  *     Makes a copy of the FST.
  *     """
  *     return _init_XFst(new fst.FstClass(deref(self._fst)))             # <<<<<<<<<<<<<<
@@ -18261,15 +17248,15 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_4_Fst_copy(struct __
   __Pyx_XDECREF(((PyObject *)__pyx_r));
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1448, __pyx_L1_error)
+    __PYX_ERR(0, 1470, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(new fst::script::FstClass((*__pyx_v_self->_fst)))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1448, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(new fst::script::FstClass((*__pyx_v_self->_fst)))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1470, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1442
+  /* "pywrapfst.pyx":1464
  *     return ArcIterator(self, state)
  * 
  *   cpdef _Fst copy(self):             # <<<<<<<<<<<<<<
@@ -18311,7 +17298,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_14copy(struct __pyx_obj_9pywrapfst__F
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("copy", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_copy(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1442, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_copy(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1464, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -18328,7 +17315,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_14copy(struct __pyx_obj_9pywrapfst__F
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1450
+/* "pywrapfst.pyx":1472
  *     return _init_XFst(new fst.FstClass(deref(self._fst)))
  * 
  *   cpdef void draw(self,             # <<<<<<<<<<<<<<
@@ -18339,7 +17326,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_14copy(struct __pyx_obj_9pywrapfst__F
 static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, PyObject *__pyx_v_filename, int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_4_Fst_draw *__pyx_optional_args) {
 
-  /* "pywrapfst.pyx":1452
+  /* "pywrapfst.pyx":1474
  *   cpdef void draw(self,
  *                   filename,
  *                   _SymbolTable isymbols=None,             # <<<<<<<<<<<<<<
@@ -18348,7 +17335,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_isymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-  /* "pywrapfst.pyx":1453
+  /* "pywrapfst.pyx":1475
  *                   filename,
  *                   _SymbolTable isymbols=None,
  *                   _SymbolTable osymbols=None,             # <<<<<<<<<<<<<<
@@ -18357,7 +17344,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_osymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-  /* "pywrapfst.pyx":1454
+  /* "pywrapfst.pyx":1476
  *                   _SymbolTable isymbols=None,
  *                   _SymbolTable osymbols=None,
  *                   SymbolTable ssymbols=None,             # <<<<<<<<<<<<<<
@@ -18366,7 +17353,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   struct __pyx_obj_9pywrapfst_SymbolTable *__pyx_v_ssymbols = ((struct __pyx_obj_9pywrapfst_SymbolTable *)Py_None);
 
-  /* "pywrapfst.pyx":1455
+  /* "pywrapfst.pyx":1477
  *                   _SymbolTable osymbols=None,
  *                   SymbolTable ssymbols=None,
  *                   bool acceptor=False,             # <<<<<<<<<<<<<<
@@ -18374,11 +17361,11 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  *                   double width=8.5,
  */
   bool __pyx_v_acceptor = ((bool)0);
-  PyObject *__pyx_v_title = ((PyObject *)__pyx_kp_b__24);
+  PyObject *__pyx_v_title = ((PyObject *)__pyx_kp_b__10);
   double __pyx_v_width = ((double)8.5);
   double __pyx_v_height = ((double)11.0);
 
-  /* "pywrapfst.pyx":1459
+  /* "pywrapfst.pyx":1481
  *                   double width=8.5,
  *                   double height=11,
  *                   bool portrait=False,             # <<<<<<<<<<<<<<
@@ -18387,7 +17374,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   bool __pyx_v_portrait = ((bool)0);
 
-  /* "pywrapfst.pyx":1460
+  /* "pywrapfst.pyx":1482
  *                   double height=11,
  *                   bool portrait=False,
  *                   bool vertical=False,             # <<<<<<<<<<<<<<
@@ -18401,7 +17388,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
   __pyx_t_10basictypes_int32 __pyx_v_precision = ((__pyx_t_10basictypes_int32)5);
   PyObject *__pyx_v_float_format = ((PyObject *)__pyx_n_b_g);
 
-  /* "pywrapfst.pyx":1466
+  /* "pywrapfst.pyx":1488
  *                   int32 precision=5,
  *                   float_format=b"g",
  *                   bool show_weight_one=False):             # <<<<<<<<<<<<<<
@@ -18485,7 +17472,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
     }
   }
 
-  /* "pywrapfst.pyx":1450
+  /* "pywrapfst.pyx":1472
  *     return _init_XFst(new fst.FstClass(deref(self._fst)))
  * 
  *   cpdef void draw(self,             # <<<<<<<<<<<<<<
@@ -18495,156 +17482,172 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_draw); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1450, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_17draw)) {
-      __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_v_acceptor); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = PyFloat_FromDouble(__pyx_v_width); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_5 = PyFloat_FromDouble(__pyx_v_height); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_6 = __Pyx_PyBool_FromLong(__pyx_v_portrait); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      __pyx_t_7 = __Pyx_PyBool_FromLong(__pyx_v_vertical); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_8 = PyFloat_FromDouble(__pyx_v_ranksep); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_9 = PyFloat_FromDouble(__pyx_v_nodesep); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __pyx_t_10 = __Pyx_PyInt_From_int32_t(__pyx_v_fontsize); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_10);
-      __pyx_t_11 = __Pyx_PyInt_From_int32_t(__pyx_v_precision); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_11);
-      __pyx_t_12 = __Pyx_PyBool_FromLong(__pyx_v_show_weight_one); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 1450, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_12);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_13 = __pyx_t_1; __pyx_t_14 = NULL;
-      __pyx_t_15 = 0;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_13))) {
-        __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_13);
-        if (likely(__pyx_t_14)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_13);
-          __Pyx_INCREF(__pyx_t_14);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_13, function);
-          __pyx_t_15 = 1;
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_draw); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1472, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_17draw)) {
+        __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_v_acceptor); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_4 = PyFloat_FromDouble(__pyx_v_width); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __pyx_t_5 = PyFloat_FromDouble(__pyx_v_height); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_5);
+        __pyx_t_6 = __Pyx_PyBool_FromLong(__pyx_v_portrait); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_6);
+        __pyx_t_7 = __Pyx_PyBool_FromLong(__pyx_v_vertical); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_7);
+        __pyx_t_8 = PyFloat_FromDouble(__pyx_v_ranksep); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __pyx_t_9 = PyFloat_FromDouble(__pyx_v_nodesep); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_9);
+        __pyx_t_10 = __Pyx_PyInt_From_int32_t(__pyx_v_fontsize); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_10);
+        __pyx_t_11 = __Pyx_PyInt_From_int32_t(__pyx_v_precision); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_11);
+        __pyx_t_12 = __Pyx_PyBool_FromLong(__pyx_v_show_weight_one); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 1472, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_12);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_13 = __pyx_t_1; __pyx_t_14 = NULL;
+        __pyx_t_15 = 0;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_13))) {
+          __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_13);
+          if (likely(__pyx_t_14)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_13);
+            __Pyx_INCREF(__pyx_t_14);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_13, function);
+            __pyx_t_15 = 1;
+          }
+        }
+        #if CYTHON_FAST_PYCALL
+        if (PyFunction_Check(__pyx_t_13)) {
+          PyObject *__pyx_temp[17] = {__pyx_t_14, __pyx_v_filename, ((PyObject *)__pyx_v_isymbols), ((PyObject *)__pyx_v_osymbols), ((PyObject *)__pyx_v_ssymbols), __pyx_t_3, __pyx_v_title, __pyx_t_4, __pyx_t_5, __pyx_t_6, __pyx_t_7, __pyx_t_8, __pyx_t_9, __pyx_t_10, __pyx_t_11, __pyx_v_float_format, __pyx_t_12};
+          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_13, __pyx_temp+1-__pyx_t_15, 16+__pyx_t_15); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1472, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+          __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+          __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+          __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+        } else
+        #endif
+        #if CYTHON_FAST_PYCCALL
+        if (__Pyx_PyFastCFunction_Check(__pyx_t_13)) {
+          PyObject *__pyx_temp[17] = {__pyx_t_14, __pyx_v_filename, ((PyObject *)__pyx_v_isymbols), ((PyObject *)__pyx_v_osymbols), ((PyObject *)__pyx_v_ssymbols), __pyx_t_3, __pyx_v_title, __pyx_t_4, __pyx_t_5, __pyx_t_6, __pyx_t_7, __pyx_t_8, __pyx_t_9, __pyx_t_10, __pyx_t_11, __pyx_v_float_format, __pyx_t_12};
+          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_13, __pyx_temp+1-__pyx_t_15, 16+__pyx_t_15); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1472, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+          __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+          __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+          __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+        } else
+        #endif
+        {
+          __pyx_t_16 = PyTuple_New(16+__pyx_t_15); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1472, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_16);
+          if (__pyx_t_14) {
+            __Pyx_GIVEREF(__pyx_t_14); PyTuple_SET_ITEM(__pyx_t_16, 0, __pyx_t_14); __pyx_t_14 = NULL;
+          }
+          __Pyx_INCREF(__pyx_v_filename);
+          __Pyx_GIVEREF(__pyx_v_filename);
+          PyTuple_SET_ITEM(__pyx_t_16, 0+__pyx_t_15, __pyx_v_filename);
+          __Pyx_INCREF(((PyObject *)__pyx_v_isymbols));
+          __Pyx_GIVEREF(((PyObject *)__pyx_v_isymbols));
+          PyTuple_SET_ITEM(__pyx_t_16, 1+__pyx_t_15, ((PyObject *)__pyx_v_isymbols));
+          __Pyx_INCREF(((PyObject *)__pyx_v_osymbols));
+          __Pyx_GIVEREF(((PyObject *)__pyx_v_osymbols));
+          PyTuple_SET_ITEM(__pyx_t_16, 2+__pyx_t_15, ((PyObject *)__pyx_v_osymbols));
+          __Pyx_INCREF(((PyObject *)__pyx_v_ssymbols));
+          __Pyx_GIVEREF(((PyObject *)__pyx_v_ssymbols));
+          PyTuple_SET_ITEM(__pyx_t_16, 3+__pyx_t_15, ((PyObject *)__pyx_v_ssymbols));
+          __Pyx_GIVEREF(__pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_16, 4+__pyx_t_15, __pyx_t_3);
+          __Pyx_INCREF(__pyx_v_title);
+          __Pyx_GIVEREF(__pyx_v_title);
+          PyTuple_SET_ITEM(__pyx_t_16, 5+__pyx_t_15, __pyx_v_title);
+          __Pyx_GIVEREF(__pyx_t_4);
+          PyTuple_SET_ITEM(__pyx_t_16, 6+__pyx_t_15, __pyx_t_4);
+          __Pyx_GIVEREF(__pyx_t_5);
+          PyTuple_SET_ITEM(__pyx_t_16, 7+__pyx_t_15, __pyx_t_5);
+          __Pyx_GIVEREF(__pyx_t_6);
+          PyTuple_SET_ITEM(__pyx_t_16, 8+__pyx_t_15, __pyx_t_6);
+          __Pyx_GIVEREF(__pyx_t_7);
+          PyTuple_SET_ITEM(__pyx_t_16, 9+__pyx_t_15, __pyx_t_7);
+          __Pyx_GIVEREF(__pyx_t_8);
+          PyTuple_SET_ITEM(__pyx_t_16, 10+__pyx_t_15, __pyx_t_8);
+          __Pyx_GIVEREF(__pyx_t_9);
+          PyTuple_SET_ITEM(__pyx_t_16, 11+__pyx_t_15, __pyx_t_9);
+          __Pyx_GIVEREF(__pyx_t_10);
+          PyTuple_SET_ITEM(__pyx_t_16, 12+__pyx_t_15, __pyx_t_10);
+          __Pyx_GIVEREF(__pyx_t_11);
+          PyTuple_SET_ITEM(__pyx_t_16, 13+__pyx_t_15, __pyx_t_11);
+          __Pyx_INCREF(__pyx_v_float_format);
+          __Pyx_GIVEREF(__pyx_v_float_format);
+          PyTuple_SET_ITEM(__pyx_t_16, 14+__pyx_t_15, __pyx_v_float_format);
+          __Pyx_GIVEREF(__pyx_t_12);
+          PyTuple_SET_ITEM(__pyx_t_16, 15+__pyx_t_15, __pyx_t_12);
+          __pyx_t_3 = 0;
+          __pyx_t_4 = 0;
+          __pyx_t_5 = 0;
+          __pyx_t_6 = 0;
+          __pyx_t_7 = 0;
+          __pyx_t_8 = 0;
+          __pyx_t_9 = 0;
+          __pyx_t_10 = 0;
+          __pyx_t_11 = 0;
+          __pyx_t_12 = 0;
+          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_13, __pyx_t_16, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1472, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
         }
+        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_13)) {
-        PyObject *__pyx_temp[17] = {__pyx_t_14, __pyx_v_filename, ((PyObject *)__pyx_v_isymbols), ((PyObject *)__pyx_v_osymbols), ((PyObject *)__pyx_v_ssymbols), __pyx_t_3, __pyx_v_title, __pyx_t_4, __pyx_t_5, __pyx_t_6, __pyx_t_7, __pyx_t_8, __pyx_t_9, __pyx_t_10, __pyx_t_11, __pyx_v_float_format, __pyx_t_12};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_13, __pyx_temp+1-__pyx_t_15, 16+__pyx_t_15); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1450, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-        __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-        __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_13)) {
-        PyObject *__pyx_temp[17] = {__pyx_t_14, __pyx_v_filename, ((PyObject *)__pyx_v_isymbols), ((PyObject *)__pyx_v_osymbols), ((PyObject *)__pyx_v_ssymbols), __pyx_t_3, __pyx_v_title, __pyx_t_4, __pyx_t_5, __pyx_t_6, __pyx_t_7, __pyx_t_8, __pyx_t_9, __pyx_t_10, __pyx_t_11, __pyx_v_float_format, __pyx_t_12};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_13, __pyx_temp+1-__pyx_t_15, 16+__pyx_t_15); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1450, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-        __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-        __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_16 = PyTuple_New(16+__pyx_t_15); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1450, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_16);
-        if (__pyx_t_14) {
-          __Pyx_GIVEREF(__pyx_t_14); PyTuple_SET_ITEM(__pyx_t_16, 0, __pyx_t_14); __pyx_t_14 = NULL;
-        }
-        __Pyx_INCREF(__pyx_v_filename);
-        __Pyx_GIVEREF(__pyx_v_filename);
-        PyTuple_SET_ITEM(__pyx_t_16, 0+__pyx_t_15, __pyx_v_filename);
-        __Pyx_INCREF(((PyObject *)__pyx_v_isymbols));
-        __Pyx_GIVEREF(((PyObject *)__pyx_v_isymbols));
-        PyTuple_SET_ITEM(__pyx_t_16, 1+__pyx_t_15, ((PyObject *)__pyx_v_isymbols));
-        __Pyx_INCREF(((PyObject *)__pyx_v_osymbols));
-        __Pyx_GIVEREF(((PyObject *)__pyx_v_osymbols));
-        PyTuple_SET_ITEM(__pyx_t_16, 2+__pyx_t_15, ((PyObject *)__pyx_v_osymbols));
-        __Pyx_INCREF(((PyObject *)__pyx_v_ssymbols));
-        __Pyx_GIVEREF(((PyObject *)__pyx_v_ssymbols));
-        PyTuple_SET_ITEM(__pyx_t_16, 3+__pyx_t_15, ((PyObject *)__pyx_v_ssymbols));
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_16, 4+__pyx_t_15, __pyx_t_3);
-        __Pyx_INCREF(__pyx_v_title);
-        __Pyx_GIVEREF(__pyx_v_title);
-        PyTuple_SET_ITEM(__pyx_t_16, 5+__pyx_t_15, __pyx_v_title);
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_16, 6+__pyx_t_15, __pyx_t_4);
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_16, 7+__pyx_t_15, __pyx_t_5);
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_16, 8+__pyx_t_15, __pyx_t_6);
-        __Pyx_GIVEREF(__pyx_t_7);
-        PyTuple_SET_ITEM(__pyx_t_16, 9+__pyx_t_15, __pyx_t_7);
-        __Pyx_GIVEREF(__pyx_t_8);
-        PyTuple_SET_ITEM(__pyx_t_16, 10+__pyx_t_15, __pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_9);
-        PyTuple_SET_ITEM(__pyx_t_16, 11+__pyx_t_15, __pyx_t_9);
-        __Pyx_GIVEREF(__pyx_t_10);
-        PyTuple_SET_ITEM(__pyx_t_16, 12+__pyx_t_15, __pyx_t_10);
-        __Pyx_GIVEREF(__pyx_t_11);
-        PyTuple_SET_ITEM(__pyx_t_16, 13+__pyx_t_15, __pyx_t_11);
-        __Pyx_INCREF(__pyx_v_float_format);
-        __Pyx_GIVEREF(__pyx_v_float_format);
-        PyTuple_SET_ITEM(__pyx_t_16, 14+__pyx_t_15, __pyx_v_float_format);
-        __Pyx_GIVEREF(__pyx_t_12);
-        PyTuple_SET_ITEM(__pyx_t_16, 15+__pyx_t_15, __pyx_t_12);
-        __pyx_t_3 = 0;
-        __pyx_t_4 = 0;
-        __pyx_t_5 = 0;
-        __pyx_t_6 = 0;
-        __pyx_t_7 = 0;
-        __pyx_t_8 = 0;
-        __pyx_t_9 = 0;
-        __pyx_t_10 = 0;
-        __pyx_t_11 = 0;
-        __pyx_t_12 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_13, __pyx_t_16, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1450, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1500
+  /* "pywrapfst.pyx":1522
  *     See also: `text`.
  *     """
  *     cdef string filename_string = tostring(filename)             # <<<<<<<<<<<<<<
  *     cdef unique_ptr[ofstream] ostrm
  *     ostrm.reset(new ofstream(filename_string))
  */
-  __pyx_t_17 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1500, __pyx_L1_error)
+  __pyx_t_17 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1522, __pyx_L1_error)
   __pyx_v_filename_string = __pyx_t_17;
 
-  /* "pywrapfst.pyx":1502
+  /* "pywrapfst.pyx":1524
  *     cdef string filename_string = tostring(filename)
  *     cdef unique_ptr[ofstream] ostrm
  *     ostrm.reset(new ofstream(filename_string))             # <<<<<<<<<<<<<<
@@ -18653,7 +17656,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   __pyx_v_ostrm.reset(new std::ofstream(__pyx_v_filename_string));
 
-  /* "pywrapfst.pyx":1503
+  /* "pywrapfst.pyx":1525
  *     cdef unique_ptr[ofstream] ostrm
  *     ostrm.reset(new ofstream(filename_string))
  *     cdef fst.SymbolTable *ssymbols_ptr = NULL             # <<<<<<<<<<<<<<
@@ -18662,7 +17665,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   __pyx_v_ssymbols_ptr = NULL;
 
-  /* "pywrapfst.pyx":1504
+  /* "pywrapfst.pyx":1526
  *     ostrm.reset(new ofstream(filename_string))
  *     cdef fst.SymbolTable *ssymbols_ptr = NULL
  *     if ssymbols is not None:             # <<<<<<<<<<<<<<
@@ -18673,7 +17676,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
   __pyx_t_19 = (__pyx_t_18 != 0);
   if (__pyx_t_19) {
 
-    /* "pywrapfst.pyx":1505
+    /* "pywrapfst.pyx":1527
  *     cdef fst.SymbolTable *ssymbols_ptr = NULL
  *     if ssymbols is not None:
  *       ssymbols_ptr = ssymbols._table             # <<<<<<<<<<<<<<
@@ -18682,12 +17685,12 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
     if (unlikely(((PyObject *)__pyx_v_ssymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 1505, __pyx_L1_error)
+      __PYX_ERR(0, 1527, __pyx_L1_error)
     }
     __pyx_t_20 = __pyx_v_ssymbols->__pyx_base.__pyx_base._table;
     __pyx_v_ssymbols_ptr = __pyx_t_20;
 
-    /* "pywrapfst.pyx":1504
+    /* "pywrapfst.pyx":1526
  *     ostrm.reset(new ofstream(filename_string))
  *     cdef fst.SymbolTable *ssymbols_ptr = NULL
  *     if ssymbols is not None:             # <<<<<<<<<<<<<<
@@ -18696,7 +17699,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   }
 
-  /* "pywrapfst.pyx":1506
+  /* "pywrapfst.pyx":1528
  *     if ssymbols is not None:
  *       ssymbols_ptr = ssymbols._table
  *     fst.DrawFst(deref(self._fst),             # <<<<<<<<<<<<<<
@@ -18705,10 +17708,10 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1506, __pyx_L1_error)
+    __PYX_ERR(0, 1528, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":1507
+  /* "pywrapfst.pyx":1529
  *       ssymbols_ptr = ssymbols._table
  *     fst.DrawFst(deref(self._fst),
  *         self._fst.get().InputSymbols() if isymbols is None             # <<<<<<<<<<<<<<
@@ -18719,12 +17722,12 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
   if ((__pyx_t_19 != 0)) {
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-      __PYX_ERR(0, 1507, __pyx_L1_error)
+      __PYX_ERR(0, 1529, __pyx_L1_error)
     }
     __pyx_t_21 = __pyx_v_self->_fst.get()->InputSymbols();
   } else {
 
-    /* "pywrapfst.pyx":1508
+    /* "pywrapfst.pyx":1530
  *     fst.DrawFst(deref(self._fst),
  *         self._fst.get().InputSymbols() if isymbols is None
  *         else isymbols._table,             # <<<<<<<<<<<<<<
@@ -18733,12 +17736,12 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
     if (unlikely(((PyObject *)__pyx_v_isymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 1508, __pyx_L1_error)
+      __PYX_ERR(0, 1530, __pyx_L1_error)
     }
     __pyx_t_21 = __pyx_v_isymbols->_table;
   }
 
-  /* "pywrapfst.pyx":1509
+  /* "pywrapfst.pyx":1531
  *         self._fst.get().InputSymbols() if isymbols is None
  *         else isymbols._table,
  *         self._fst.get().OutputSymbols() if osymbols is None             # <<<<<<<<<<<<<<
@@ -18749,12 +17752,12 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
   if ((__pyx_t_19 != 0)) {
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-      __PYX_ERR(0, 1509, __pyx_L1_error)
+      __PYX_ERR(0, 1531, __pyx_L1_error)
     }
     __pyx_t_22 = __pyx_v_self->_fst.get()->OutputSymbols();
   } else {
 
-    /* "pywrapfst.pyx":1510
+    /* "pywrapfst.pyx":1532
  *         else isymbols._table,
  *         self._fst.get().OutputSymbols() if osymbols is None
  *         else osymbols._table,             # <<<<<<<<<<<<<<
@@ -18763,30 +17766,30 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
     if (unlikely(((PyObject *)__pyx_v_osymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 1510, __pyx_L1_error)
+      __PYX_ERR(0, 1532, __pyx_L1_error)
     }
     __pyx_t_22 = __pyx_v_osymbols->_table;
   }
 
-  /* "pywrapfst.pyx":1511
+  /* "pywrapfst.pyx":1533
  *         self._fst.get().OutputSymbols() if osymbols is None
  *         else osymbols._table,
  *         ssymbols_ptr, acceptor, tostring(title), width, height, portrait,             # <<<<<<<<<<<<<<
  *         vertical, ranksep, nodesep, fontsize, precision,
  *         tostring(float_format), show_weight_one, ostrm.get(),
  */
-  __pyx_t_17 = __pyx_f_9pywrapfst_tostring(__pyx_v_title, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1511, __pyx_L1_error)
+  __pyx_t_17 = __pyx_f_9pywrapfst_tostring(__pyx_v_title, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1533, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1513
+  /* "pywrapfst.pyx":1535
  *         ssymbols_ptr, acceptor, tostring(title), width, height, portrait,
  *         vertical, ranksep, nodesep, fontsize, precision,
  *         tostring(float_format), show_weight_one, ostrm.get(),             # <<<<<<<<<<<<<<
  *         filename_string)
  * 
  */
-  __pyx_t_23 = __pyx_f_9pywrapfst_tostring(__pyx_v_float_format, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1513, __pyx_L1_error)
+  __pyx_t_23 = __pyx_f_9pywrapfst_tostring(__pyx_v_float_format, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1535, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1506
+  /* "pywrapfst.pyx":1528
  *     if ssymbols is not None:
  *       ssymbols_ptr = ssymbols._table
  *     fst.DrawFst(deref(self._fst),             # <<<<<<<<<<<<<<
@@ -18795,7 +17798,7 @@ static void __pyx_f_9pywrapfst_4_Fst_draw(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   fst::script::DrawFst((*__pyx_v_self->_fst), __pyx_t_21, __pyx_t_22, __pyx_v_ssymbols_ptr, __pyx_v_acceptor, __pyx_t_17, __pyx_v_width, __pyx_v_height, __pyx_v_portrait, __pyx_v_vertical, __pyx_v_ranksep, __pyx_v_nodesep, __pyx_v_fontsize, __pyx_v_precision, __pyx_t_23, __pyx_v_show_weight_one, __pyx_v_ostrm.get(), __pyx_v_filename_string);
 
-  /* "pywrapfst.pyx":1450
+  /* "pywrapfst.pyx":1472
  *     return _init_XFst(new fst.FstClass(deref(self._fst)))
  * 
  *   cpdef void draw(self,             # <<<<<<<<<<<<<<
@@ -18853,7 +17856,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_filename,&__pyx_n_s_isymbols,&__pyx_n_s_osymbols,&__pyx_n_s_ssymbols,&__pyx_n_s_acceptor,&__pyx_n_s_title,&__pyx_n_s_width,&__pyx_n_s_height,&__pyx_n_s_portrait,&__pyx_n_s_vertical,&__pyx_n_s_ranksep,&__pyx_n_s_nodesep,&__pyx_n_s_fontsize,&__pyx_n_s_precision,&__pyx_n_s_float_format,&__pyx_n_s_show_weight_one,0};
     PyObject* values[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 
-    /* "pywrapfst.pyx":1452
+    /* "pywrapfst.pyx":1474
  *   cpdef void draw(self,
  *                   filename,
  *                   _SymbolTable isymbols=None,             # <<<<<<<<<<<<<<
@@ -18862,7 +17865,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
  */
     values[1] = (PyObject *)((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-    /* "pywrapfst.pyx":1453
+    /* "pywrapfst.pyx":1475
  *                   filename,
  *                   _SymbolTable isymbols=None,
  *                   _SymbolTable osymbols=None,             # <<<<<<<<<<<<<<
@@ -18871,7 +17874,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
  */
     values[2] = (PyObject *)((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-    /* "pywrapfst.pyx":1454
+    /* "pywrapfst.pyx":1476
  *                   _SymbolTable isymbols=None,
  *                   _SymbolTable osymbols=None,
  *                   SymbolTable ssymbols=None,             # <<<<<<<<<<<<<<
@@ -18879,7 +17882,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
  *                   title=b"",
  */
     values[3] = (PyObject *)((struct __pyx_obj_9pywrapfst_SymbolTable *)Py_None);
-    values[5] = ((PyObject *)__pyx_kp_b__24);
+    values[5] = ((PyObject *)__pyx_kp_b__10);
     values[14] = ((PyObject *)__pyx_n_b_g);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
@@ -19017,7 +18020,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "draw") < 0)) __PYX_ERR(0, 1450, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "draw") < 0)) __PYX_ERR(0, 1472, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -19061,10 +18064,10 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
     __pyx_v_osymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)values[2]);
     __pyx_v_ssymbols = ((struct __pyx_obj_9pywrapfst_SymbolTable *)values[3]);
     if (values[4]) {
-      __pyx_v_acceptor = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_acceptor == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1455, __pyx_L3_error)
+      __pyx_v_acceptor = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_acceptor == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1477, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":1455
+      /* "pywrapfst.pyx":1477
  *                   _SymbolTable osymbols=None,
  *                   SymbolTable ssymbols=None,
  *                   bool acceptor=False,             # <<<<<<<<<<<<<<
@@ -19075,20 +18078,20 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
     }
     __pyx_v_title = values[5];
     if (values[6]) {
-      __pyx_v_width = __pyx_PyFloat_AsDouble(values[6]); if (unlikely((__pyx_v_width == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1457, __pyx_L3_error)
+      __pyx_v_width = __pyx_PyFloat_AsDouble(values[6]); if (unlikely((__pyx_v_width == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1479, __pyx_L3_error)
     } else {
       __pyx_v_width = ((double)8.5);
     }
     if (values[7]) {
-      __pyx_v_height = __pyx_PyFloat_AsDouble(values[7]); if (unlikely((__pyx_v_height == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1458, __pyx_L3_error)
+      __pyx_v_height = __pyx_PyFloat_AsDouble(values[7]); if (unlikely((__pyx_v_height == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1480, __pyx_L3_error)
     } else {
       __pyx_v_height = ((double)11.0);
     }
     if (values[8]) {
-      __pyx_v_portrait = __Pyx_PyObject_IsTrue(values[8]); if (unlikely((__pyx_v_portrait == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1459, __pyx_L3_error)
+      __pyx_v_portrait = __Pyx_PyObject_IsTrue(values[8]); if (unlikely((__pyx_v_portrait == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1481, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":1459
+      /* "pywrapfst.pyx":1481
  *                   double width=8.5,
  *                   double height=11,
  *                   bool portrait=False,             # <<<<<<<<<<<<<<
@@ -19098,10 +18101,10 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
       __pyx_v_portrait = ((bool)0);
     }
     if (values[9]) {
-      __pyx_v_vertical = __Pyx_PyObject_IsTrue(values[9]); if (unlikely((__pyx_v_vertical == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1460, __pyx_L3_error)
+      __pyx_v_vertical = __Pyx_PyObject_IsTrue(values[9]); if (unlikely((__pyx_v_vertical == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1482, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":1460
+      /* "pywrapfst.pyx":1482
  *                   double height=11,
  *                   bool portrait=False,
  *                   bool vertical=False,             # <<<<<<<<<<<<<<
@@ -19111,31 +18114,31 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
       __pyx_v_vertical = ((bool)0);
     }
     if (values[10]) {
-      __pyx_v_ranksep = __pyx_PyFloat_AsDouble(values[10]); if (unlikely((__pyx_v_ranksep == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1461, __pyx_L3_error)
+      __pyx_v_ranksep = __pyx_PyFloat_AsDouble(values[10]); if (unlikely((__pyx_v_ranksep == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1483, __pyx_L3_error)
     } else {
       __pyx_v_ranksep = ((double)0.4);
     }
     if (values[11]) {
-      __pyx_v_nodesep = __pyx_PyFloat_AsDouble(values[11]); if (unlikely((__pyx_v_nodesep == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1462, __pyx_L3_error)
+      __pyx_v_nodesep = __pyx_PyFloat_AsDouble(values[11]); if (unlikely((__pyx_v_nodesep == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1484, __pyx_L3_error)
     } else {
       __pyx_v_nodesep = ((double)0.25);
     }
     if (values[12]) {
-      __pyx_v_fontsize = __Pyx_PyInt_As_int32_t(values[12]); if (unlikely((__pyx_v_fontsize == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1463, __pyx_L3_error)
+      __pyx_v_fontsize = __Pyx_PyInt_As_int32_t(values[12]); if (unlikely((__pyx_v_fontsize == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1485, __pyx_L3_error)
     } else {
       __pyx_v_fontsize = ((__pyx_t_10basictypes_int32)14);
     }
     if (values[13]) {
-      __pyx_v_precision = __Pyx_PyInt_As_int32_t(values[13]); if (unlikely((__pyx_v_precision == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1464, __pyx_L3_error)
+      __pyx_v_precision = __Pyx_PyInt_As_int32_t(values[13]); if (unlikely((__pyx_v_precision == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1486, __pyx_L3_error)
     } else {
       __pyx_v_precision = ((__pyx_t_10basictypes_int32)5);
     }
     __pyx_v_float_format = values[14];
     if (values[15]) {
-      __pyx_v_show_weight_one = __Pyx_PyObject_IsTrue(values[15]); if (unlikely((__pyx_v_show_weight_one == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1466, __pyx_L3_error)
+      __pyx_v_show_weight_one = __Pyx_PyObject_IsTrue(values[15]); if (unlikely((__pyx_v_show_weight_one == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1488, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":1466
+      /* "pywrapfst.pyx":1488
  *                   int32 precision=5,
  *                   float_format=b"g",
  *                   bool show_weight_one=False):             # <<<<<<<<<<<<<<
@@ -19147,18 +18150,18 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_17draw(PyObject *__pyx_v_self, PyObje
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("draw", 0, 1, 16, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1450, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("draw", 0, 1, 16, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1472, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._Fst.draw", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_isymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "isymbols", 0))) __PYX_ERR(0, 1452, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_osymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "osymbols", 0))) __PYX_ERR(0, 1453, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ssymbols), __pyx_ptype_9pywrapfst_SymbolTable, 1, "ssymbols", 0))) __PYX_ERR(0, 1454, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_isymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "isymbols", 0))) __PYX_ERR(0, 1474, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_osymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "osymbols", 0))) __PYX_ERR(0, 1475, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ssymbols), __pyx_ptype_9pywrapfst_SymbolTable, 1, "ssymbols", 0))) __PYX_ERR(0, 1476, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_4_Fst_16draw(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), __pyx_v_filename, __pyx_v_isymbols, __pyx_v_osymbols, __pyx_v_ssymbols, __pyx_v_acceptor, __pyx_v_title, __pyx_v_width, __pyx_v_height, __pyx_v_portrait, __pyx_v_vertical, __pyx_v_ranksep, __pyx_v_nodesep, __pyx_v_fontsize, __pyx_v_precision, __pyx_v_float_format, __pyx_v_show_weight_one);
 
-  /* "pywrapfst.pyx":1450
+  /* "pywrapfst.pyx":1472
  *     return _init_XFst(new fst.FstClass(deref(self._fst)))
  * 
  *   cpdef void draw(self,             # <<<<<<<<<<<<<<
@@ -19199,7 +18202,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_16draw(struct __pyx_obj_9pywrapfst__F
   __pyx_t_1.float_format = __pyx_v_float_format;
   __pyx_t_1.show_weight_one = __pyx_v_show_weight_one;
   __pyx_vtabptr_9pywrapfst__Fst->draw(__pyx_v_self, __pyx_v_filename, 1, &__pyx_t_1); 
-  __pyx_t_2 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1450, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1472, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -19216,7 +18219,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_16draw(struct __pyx_obj_9pywrapfst__F
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1516
+/* "pywrapfst.pyx":1538
  *         filename_string)
  * 
  *   cpdef Weight final(self, int64 state):             # <<<<<<<<<<<<<<
@@ -19234,106 +18237,143 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst_4_Fst_final(struct
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
+  int __pyx_t_6;
   __Pyx_RefNannySetupContext("final", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_final); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1516, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_19final)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1516, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_final); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1538, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_19final)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1538, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1516, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1538, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1516, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1516, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1516, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1516, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_Weight))))) __PYX_ERR(0, 1538, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_Weight))))) __PYX_ERR(0, 1516, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1531
+  /* "pywrapfst.pyx":1553
  *       FstIndexError: State index out of range.
  *     """
  *     cdef Weight weight = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *     weight._weight.reset(new fst.WeightClass(self._fst.get().Final(state)))
- *     return weight
+ *     if weight.to_string() == b"BadNumber":
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1531, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1553, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_weight = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":1532
+  /* "pywrapfst.pyx":1554
  *     """
  *     cdef Weight weight = Weight.__new__(Weight)
  *     weight._weight.reset(new fst.WeightClass(self._fst.get().Final(state)))             # <<<<<<<<<<<<<<
- *     return weight
- * 
+ *     if weight.to_string() == b"BadNumber":
+ *       raise FstIndexError("State index out of range")
  */
   if (unlikely(((PyObject *)__pyx_v_weight) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 1532, __pyx_L1_error)
+    __PYX_ERR(0, 1554, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1532, __pyx_L1_error)
+    __PYX_ERR(0, 1554, __pyx_L1_error)
   }
   __pyx_v_weight->_weight.reset(new fst::script::WeightClass(__pyx_v_self->_fst.get()->Final(__pyx_v_state)));
 
-  /* "pywrapfst.pyx":1533
+  /* "pywrapfst.pyx":1555
  *     cdef Weight weight = Weight.__new__(Weight)
  *     weight._weight.reset(new fst.WeightClass(self._fst.get().Final(state)))
+ *     if weight.to_string() == b"BadNumber":             # <<<<<<<<<<<<<<
+ *       raise FstIndexError("State index out of range")
+ *     return weight
+ */
+  if (unlikely(((PyObject *)__pyx_v_weight) == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "to_string");
+    __PYX_ERR(0, 1555, __pyx_L1_error)
+  }
+  __pyx_t_6 = ((((struct __pyx_vtabstruct_9pywrapfst_Weight *)__pyx_v_weight->__pyx_vtab)->to_string(__pyx_v_weight, 0) == ((char const *)"BadNumber")) != 0);
+  if (unlikely(__pyx_t_6)) {
+
+    /* "pywrapfst.pyx":1556
+ *     weight._weight.reset(new fst.WeightClass(self._fst.get().Final(state)))
+ *     if weight.to_string() == b"BadNumber":
+ *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
+ *     return weight
+ * 
+ */
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1556, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1556, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 1556, __pyx_L1_error)
+
+    /* "pywrapfst.pyx":1555
+ *     cdef Weight weight = Weight.__new__(Weight)
+ *     weight._weight.reset(new fst.WeightClass(self._fst.get().Final(state)))
+ *     if weight.to_string() == b"BadNumber":             # <<<<<<<<<<<<<<
+ *       raise FstIndexError("State index out of range")
+ *     return weight
+ */
+  }
+
+  /* "pywrapfst.pyx":1557
+ *     if weight.to_string() == b"BadNumber":
+ *       raise FstIndexError("State index out of range")
  *     return weight             # <<<<<<<<<<<<<<
  * 
  *   cpdef string fst_type(self):
@@ -19343,7 +18383,7 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst_4_Fst_final(struct
   __pyx_r = __pyx_v_weight;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1516
+  /* "pywrapfst.pyx":1538
  *         filename_string)
  * 
  *   cpdef Weight final(self, int64 state):             # <<<<<<<<<<<<<<
@@ -19358,7 +18398,6 @@ static struct __pyx_obj_9pywrapfst_Weight *__pyx_f_9pywrapfst_4_Fst_final(struct
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_AddTraceback("pywrapfst._Fst.final", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -19377,7 +18416,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_19final(PyObject *__pyx_v_self, PyObj
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("final (wrapper)", 0);
   assert(__pyx_arg_state); {
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1516, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1538, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -19398,7 +18437,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_18final(struct __pyx_obj_9pywrapfst__
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("final", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_final(__pyx_v_self, __pyx_v_state, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1516, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_final(__pyx_v_self, __pyx_v_state, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1538, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -19415,7 +18454,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_18final(struct __pyx_obj_9pywrapfst__
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1535
+/* "pywrapfst.pyx":1559
  *     return weight
  * 
  *   cpdef string fst_type(self):             # <<<<<<<<<<<<<<
@@ -19436,39 +18475,52 @@ static std::string __pyx_f_9pywrapfst_4_Fst_fst_type(struct __pyx_obj_9pywrapfst
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_fst_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1535, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_21fst_type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_fst_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1559, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_21fst_type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1559, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1559, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1535, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1535, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1535, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1541
+  /* "pywrapfst.pyx":1565
  *     Returns a string indicating the FST type.
  *     """
  *     return self._fst.get().FstType()             # <<<<<<<<<<<<<<
@@ -19477,12 +18529,12 @@ static std::string __pyx_f_9pywrapfst_4_Fst_fst_type(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1541, __pyx_L1_error)
+    __PYX_ERR(0, 1565, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_fst.get()->FstType();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1535
+  /* "pywrapfst.pyx":1559
  *     return weight
  * 
  *   cpdef string fst_type(self):             # <<<<<<<<<<<<<<
@@ -19523,7 +18575,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_20fst_type(struct __pyx_obj_9pywrapfs
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("fst_type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_4_Fst_fst_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1535, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_4_Fst_fst_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1559, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -19540,7 +18592,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_20fst_type(struct __pyx_obj_9pywrapfs
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1543
+/* "pywrapfst.pyx":1567
  *     return self._fst.get().FstType()
  * 
  *   cpdef _FstSymbolTable input_symbols(self):             # <<<<<<<<<<<<<<
@@ -19562,40 +18614,53 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_inp
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_input_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1543, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_23input_symbols)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_input_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1567, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_23input_symbols)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1567, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__FstSymbolTable))))) __PYX_ERR(0, 1567, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst__FstSymbolTable *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1543, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1543, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__FstSymbolTable))))) __PYX_ERR(0, 1543, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst__FstSymbolTable *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1552
+  /* "pywrapfst.pyx":1576
  *     """
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *       self._fst.get().InputSymbols())             # <<<<<<<<<<<<<<
@@ -19604,10 +18669,10 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_inp
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1552, __pyx_L1_error)
+    __PYX_ERR(0, 1576, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":1551
+  /* "pywrapfst.pyx":1575
  *     See also: `input_symbols`.
  *     """
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](             # <<<<<<<<<<<<<<
@@ -19616,7 +18681,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_inp
  */
   __pyx_v_syms = const_cast<__pyx_t_9pywrapfst_SymbolTable_ptr>(__pyx_v_self->_fst.get()->InputSymbols());
 
-  /* "pywrapfst.pyx":1553
+  /* "pywrapfst.pyx":1577
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *       self._fst.get().InputSymbols())
  *     if syms == NULL:             # <<<<<<<<<<<<<<
@@ -19626,7 +18691,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_inp
   __pyx_t_5 = ((__pyx_v_syms == NULL) != 0);
   if (__pyx_t_5) {
 
-    /* "pywrapfst.pyx":1554
+    /* "pywrapfst.pyx":1578
  *       self._fst.get().InputSymbols())
  *     if syms == NULL:
  *       return             # <<<<<<<<<<<<<<
@@ -19637,7 +18702,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_inp
     __pyx_r = ((struct __pyx_obj_9pywrapfst__FstSymbolTable *)Py_None); __Pyx_INCREF(Py_None);
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":1553
+    /* "pywrapfst.pyx":1577
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *       self._fst.get().InputSymbols())
  *     if syms == NULL:             # <<<<<<<<<<<<<<
@@ -19646,7 +18711,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_inp
  */
   }
 
-  /* "pywrapfst.pyx":1555
+  /* "pywrapfst.pyx":1579
  *     if syms == NULL:
  *       return
  *     return _init_FstSymbolTable(syms, self._fst)             # <<<<<<<<<<<<<<
@@ -19656,15 +18721,15 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_inp
   __Pyx_XDECREF(((PyObject *)__pyx_r));
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1555, __pyx_L1_error)
+    __PYX_ERR(0, 1579, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_FstSymbolTable(__pyx_v_syms, __pyx_v_self->_fst)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1555, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_FstSymbolTable(__pyx_v_syms, __pyx_v_self->_fst)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1579, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__FstSymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1543
+  /* "pywrapfst.pyx":1567
  *     return self._fst.get().FstType()
  * 
  *   cpdef _FstSymbolTable input_symbols(self):             # <<<<<<<<<<<<<<
@@ -19706,7 +18771,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_22input_symbols(struct __pyx_obj_9pyw
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("input_symbols", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_input_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1543, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_input_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1567, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -19723,7 +18788,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_22input_symbols(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1557
+/* "pywrapfst.pyx":1581
  *     return _init_FstSymbolTable(syms, self._fst)
  * 
  *   cpdef size_t num_arcs(self, int64 state) except *:             # <<<<<<<<<<<<<<
@@ -19741,76 +18806,61 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_arcs(struct __pyx_obj_9pywrapfst__Fst
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  size_t __pyx_t_7;
-  int __pyx_t_8;
+  size_t __pyx_t_6;
+  int __pyx_t_7;
   __Pyx_RefNannySetupContext("num_arcs", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_arcs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1557, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_25num_arcs)) {
-      __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1557, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_arcs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1581, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_25num_arcs)) {
+        __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1581, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1557, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1581, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1557, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1557, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1557, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1557, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_6 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_6 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1581, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_6;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_7 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_7 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1557, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_7;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1574
+  /* "pywrapfst.pyx":1598
  *     See also: `num_states`.
  *     """
  *     cdef size_t result = self._fst.get().NumArcs(state)             # <<<<<<<<<<<<<<
@@ -19819,37 +18869,49 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_arcs(struct __pyx_obj_9pywrapfst__Fst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1574, __pyx_L1_error)
+    __PYX_ERR(0, 1598, __pyx_L1_error)
   }
   __pyx_v_result = __pyx_v_self->_fst.get()->NumArcs(__pyx_v_state);
 
-  /* "pywrapfst.pyx":1575
+  /* "pywrapfst.pyx":1599
  *     """
  *     cdef size_t result = self._fst.get().NumArcs(state)
  *     if result == SIZE_MAX:             # <<<<<<<<<<<<<<
  *       raise FstIndexError("State index out of range")
  *     return result
  */
-  __pyx_t_8 = ((__pyx_v_result == SIZE_MAX) != 0);
-  if (unlikely(__pyx_t_8)) {
+  __pyx_t_7 = ((__pyx_v_result == SIZE_MAX) != 0);
+  if (unlikely(__pyx_t_7)) {
 
-    /* "pywrapfst.pyx":1576
+    /* "pywrapfst.pyx":1600
  *     cdef size_t result = self._fst.get().NumArcs(state)
  *     if result == SIZE_MAX:
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     return result
  * 
  */
-    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1576, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__26, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1576, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1600, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1600, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 1576, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 1600, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1575
+    /* "pywrapfst.pyx":1599
  *     """
  *     cdef size_t result = self._fst.get().NumArcs(state)
  *     if result == SIZE_MAX:             # <<<<<<<<<<<<<<
@@ -19858,7 +18920,7 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_arcs(struct __pyx_obj_9pywrapfst__Fst
  */
   }
 
-  /* "pywrapfst.pyx":1577
+  /* "pywrapfst.pyx":1601
  *     if result == SIZE_MAX:
  *       raise FstIndexError("State index out of range")
  *     return result             # <<<<<<<<<<<<<<
@@ -19868,7 +18930,7 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_arcs(struct __pyx_obj_9pywrapfst__Fst
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1557
+  /* "pywrapfst.pyx":1581
  *     return _init_FstSymbolTable(syms, self._fst)
  * 
  *   cpdef size_t num_arcs(self, int64 state) except *:             # <<<<<<<<<<<<<<
@@ -19883,7 +18945,6 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_arcs(struct __pyx_obj_9pywrapfst__Fst
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_AddTraceback("pywrapfst._Fst.num_arcs", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -19900,7 +18961,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_25num_arcs(PyObject *__pyx_v_self, Py
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("num_arcs (wrapper)", 0);
   assert(__pyx_arg_state); {
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1557, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1581, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -19922,8 +18983,8 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_24num_arcs(struct __pyx_obj_9pywrapfs
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("num_arcs", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_9pywrapfst_4_Fst_num_arcs(__pyx_v_self, __pyx_v_state, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1557, __pyx_L1_error)
-  __pyx_t_2 = __Pyx_PyInt_FromSize_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1557, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_4_Fst_num_arcs(__pyx_v_self, __pyx_v_state, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1581, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyInt_FromSize_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1581, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -19940,7 +19001,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_24num_arcs(struct __pyx_obj_9pywrapfs
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1579
+/* "pywrapfst.pyx":1603
  *     return result
  * 
  *   cpdef size_t num_input_epsilons(self, int64 state) except *:             # <<<<<<<<<<<<<<
@@ -19958,76 +19019,61 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_input_epsilons(struct __pyx_obj_9pywr
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  size_t __pyx_t_7;
-  int __pyx_t_8;
+  size_t __pyx_t_6;
+  int __pyx_t_7;
   __Pyx_RefNannySetupContext("num_input_epsilons", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_input_epsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1579, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_27num_input_epsilons)) {
-      __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1579, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_input_epsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1603, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_27num_input_epsilons)) {
+        __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1603, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1579, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1603, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1579, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1579, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1579, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1579, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_6 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_6 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1603, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_6;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_7 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_7 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1579, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_7;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1596
+  /* "pywrapfst.pyx":1620
  *     See also: `num_output_epsilons`.
  *     """
  *     cdef size_t result = self._fst.get().NumInputEpsilons(state)             # <<<<<<<<<<<<<<
@@ -20036,37 +19082,49 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_input_epsilons(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1596, __pyx_L1_error)
+    __PYX_ERR(0, 1620, __pyx_L1_error)
   }
   __pyx_v_result = __pyx_v_self->_fst.get()->NumInputEpsilons(__pyx_v_state);
 
-  /* "pywrapfst.pyx":1597
+  /* "pywrapfst.pyx":1621
  *     """
  *     cdef size_t result = self._fst.get().NumInputEpsilons(state)
  *     if result == SIZE_MAX:             # <<<<<<<<<<<<<<
  *       raise FstIndexError("State index out of range")
  *     return result
  */
-  __pyx_t_8 = ((__pyx_v_result == SIZE_MAX) != 0);
-  if (unlikely(__pyx_t_8)) {
+  __pyx_t_7 = ((__pyx_v_result == SIZE_MAX) != 0);
+  if (unlikely(__pyx_t_7)) {
 
-    /* "pywrapfst.pyx":1598
+    /* "pywrapfst.pyx":1622
  *     cdef size_t result = self._fst.get().NumInputEpsilons(state)
  *     if result == SIZE_MAX:
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     return result
  * 
  */
-    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1598, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__27, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1598, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1622, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1622, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 1598, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 1622, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1597
+    /* "pywrapfst.pyx":1621
  *     """
  *     cdef size_t result = self._fst.get().NumInputEpsilons(state)
  *     if result == SIZE_MAX:             # <<<<<<<<<<<<<<
@@ -20075,7 +19133,7 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_input_epsilons(struct __pyx_obj_9pywr
  */
   }
 
-  /* "pywrapfst.pyx":1599
+  /* "pywrapfst.pyx":1623
  *     if result == SIZE_MAX:
  *       raise FstIndexError("State index out of range")
  *     return result             # <<<<<<<<<<<<<<
@@ -20085,7 +19143,7 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_input_epsilons(struct __pyx_obj_9pywr
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1579
+  /* "pywrapfst.pyx":1603
  *     return result
  * 
  *   cpdef size_t num_input_epsilons(self, int64 state) except *:             # <<<<<<<<<<<<<<
@@ -20100,7 +19158,6 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_input_epsilons(struct __pyx_obj_9pywr
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_AddTraceback("pywrapfst._Fst.num_input_epsilons", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -20117,7 +19174,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_27num_input_epsilons(PyObject *__pyx_
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("num_input_epsilons (wrapper)", 0);
   assert(__pyx_arg_state); {
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1579, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1603, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -20139,8 +19196,8 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_26num_input_epsilons(struct __pyx_obj
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("num_input_epsilons", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_9pywrapfst_4_Fst_num_input_epsilons(__pyx_v_self, __pyx_v_state, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1579, __pyx_L1_error)
-  __pyx_t_2 = __Pyx_PyInt_FromSize_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1579, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_4_Fst_num_input_epsilons(__pyx_v_self, __pyx_v_state, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1603, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyInt_FromSize_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1603, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -20157,7 +19214,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_26num_input_epsilons(struct __pyx_obj
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1601
+/* "pywrapfst.pyx":1625
  *     return result
  * 
  *   cpdef size_t num_output_epsilons(self, int64 state) except *:             # <<<<<<<<<<<<<<
@@ -20175,76 +19232,61 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_output_epsilons(struct __pyx_obj_9pyw
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  size_t __pyx_t_7;
-  int __pyx_t_8;
+  size_t __pyx_t_6;
+  int __pyx_t_7;
   __Pyx_RefNannySetupContext("num_output_epsilons", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_output_epsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1601, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_29num_output_epsilons)) {
-      __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1601, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_output_epsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1625, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_29num_output_epsilons)) {
+        __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1625, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1601, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1625, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1601, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1601, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1601, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1601, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_6 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_6 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1625, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_6;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_7 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_7 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1601, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_7;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1618
+  /* "pywrapfst.pyx":1642
  *     See also: `num_input_epsilons`.
  *     """
  *     cdef size_t result = self._fst.get().NumOutputEpsilons(state)             # <<<<<<<<<<<<<<
@@ -20253,37 +19295,49 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_output_epsilons(struct __pyx_obj_9pyw
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1618, __pyx_L1_error)
+    __PYX_ERR(0, 1642, __pyx_L1_error)
   }
   __pyx_v_result = __pyx_v_self->_fst.get()->NumOutputEpsilons(__pyx_v_state);
 
-  /* "pywrapfst.pyx":1619
+  /* "pywrapfst.pyx":1643
  *     """
  *     cdef size_t result = self._fst.get().NumOutputEpsilons(state)
  *     if result == SIZE_MAX:             # <<<<<<<<<<<<<<
  *       raise FstIndexError("State index out of range")
  *     return result
  */
-  __pyx_t_8 = ((__pyx_v_result == SIZE_MAX) != 0);
-  if (unlikely(__pyx_t_8)) {
+  __pyx_t_7 = ((__pyx_v_result == SIZE_MAX) != 0);
+  if (unlikely(__pyx_t_7)) {
 
-    /* "pywrapfst.pyx":1620
+    /* "pywrapfst.pyx":1644
  *     cdef size_t result = self._fst.get().NumOutputEpsilons(state)
  *     if result == SIZE_MAX:
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     return result
  * 
  */
-    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1620, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__28, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1620, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1644, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1644, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 1620, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 1644, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1619
+    /* "pywrapfst.pyx":1643
  *     """
  *     cdef size_t result = self._fst.get().NumOutputEpsilons(state)
  *     if result == SIZE_MAX:             # <<<<<<<<<<<<<<
@@ -20292,7 +19346,7 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_output_epsilons(struct __pyx_obj_9pyw
  */
   }
 
-  /* "pywrapfst.pyx":1621
+  /* "pywrapfst.pyx":1645
  *     if result == SIZE_MAX:
  *       raise FstIndexError("State index out of range")
  *     return result             # <<<<<<<<<<<<<<
@@ -20302,7 +19356,7 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_output_epsilons(struct __pyx_obj_9pyw
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1601
+  /* "pywrapfst.pyx":1625
  *     return result
  * 
  *   cpdef size_t num_output_epsilons(self, int64 state) except *:             # <<<<<<<<<<<<<<
@@ -20317,7 +19371,6 @@ static size_t __pyx_f_9pywrapfst_4_Fst_num_output_epsilons(struct __pyx_obj_9pyw
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_AddTraceback("pywrapfst._Fst.num_output_epsilons", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -20334,7 +19387,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_29num_output_epsilons(PyObject *__pyx
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("num_output_epsilons (wrapper)", 0);
   assert(__pyx_arg_state); {
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1601, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1625, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -20356,8 +19409,8 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_28num_output_epsilons(struct __pyx_ob
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("num_output_epsilons", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_9pywrapfst_4_Fst_num_output_epsilons(__pyx_v_self, __pyx_v_state, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1601, __pyx_L1_error)
-  __pyx_t_2 = __Pyx_PyInt_FromSize_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1601, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_4_Fst_num_output_epsilons(__pyx_v_self, __pyx_v_state, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1625, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyInt_FromSize_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1625, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -20374,7 +19427,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_28num_output_epsilons(struct __pyx_ob
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1623
+/* "pywrapfst.pyx":1647
  *     return result
  * 
  *   cpdef _FstSymbolTable output_symbols(self):             # <<<<<<<<<<<<<<
@@ -20396,40 +19449,53 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_out
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_output_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1623, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_31output_symbols)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_output_symbols); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1647, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_31output_symbols)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1647, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__FstSymbolTable))))) __PYX_ERR(0, 1647, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst__FstSymbolTable *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1623, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1623, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__FstSymbolTable))))) __PYX_ERR(0, 1623, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst__FstSymbolTable *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1632
+  /* "pywrapfst.pyx":1656
  *     """
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *       self._fst.get().OutputSymbols())             # <<<<<<<<<<<<<<
@@ -20438,10 +19504,10 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_out
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1632, __pyx_L1_error)
+    __PYX_ERR(0, 1656, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":1631
+  /* "pywrapfst.pyx":1655
  *     See also: `input_symbols`.
  *     """
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](             # <<<<<<<<<<<<<<
@@ -20450,7 +19516,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_out
  */
   __pyx_v_syms = const_cast<__pyx_t_9pywrapfst_SymbolTable_ptr>(__pyx_v_self->_fst.get()->OutputSymbols());
 
-  /* "pywrapfst.pyx":1633
+  /* "pywrapfst.pyx":1657
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *       self._fst.get().OutputSymbols())
  *     if syms == NULL:             # <<<<<<<<<<<<<<
@@ -20460,7 +19526,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_out
   __pyx_t_5 = ((__pyx_v_syms == NULL) != 0);
   if (__pyx_t_5) {
 
-    /* "pywrapfst.pyx":1634
+    /* "pywrapfst.pyx":1658
  *       self._fst.get().OutputSymbols())
  *     if syms == NULL:
  *       return             # <<<<<<<<<<<<<<
@@ -20471,7 +19537,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_out
     __pyx_r = ((struct __pyx_obj_9pywrapfst__FstSymbolTable *)Py_None); __Pyx_INCREF(Py_None);
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":1633
+    /* "pywrapfst.pyx":1657
  *     cdef fst.SymbolTable *syms = const_cast[SymbolTable_ptr](
  *       self._fst.get().OutputSymbols())
  *     if syms == NULL:             # <<<<<<<<<<<<<<
@@ -20480,7 +19546,7 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_out
  */
   }
 
-  /* "pywrapfst.pyx":1635
+  /* "pywrapfst.pyx":1659
  *     if syms == NULL:
  *       return
  *     return _init_FstSymbolTable(syms, self._fst)             # <<<<<<<<<<<<<<
@@ -20490,15 +19556,15 @@ static struct __pyx_obj_9pywrapfst__FstSymbolTable *__pyx_f_9pywrapfst_4_Fst_out
   __Pyx_XDECREF(((PyObject *)__pyx_r));
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1635, __pyx_L1_error)
+    __PYX_ERR(0, 1659, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_FstSymbolTable(__pyx_v_syms, __pyx_v_self->_fst)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1635, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_FstSymbolTable(__pyx_v_syms, __pyx_v_self->_fst)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1659, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__FstSymbolTable *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1623
+  /* "pywrapfst.pyx":1647
  *     return result
  * 
  *   cpdef _FstSymbolTable output_symbols(self):             # <<<<<<<<<<<<<<
@@ -20540,7 +19606,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_30output_symbols(struct __pyx_obj_9py
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("output_symbols", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_output_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1623, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_output_symbols(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1647, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -20557,7 +19623,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_30output_symbols(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1637
+/* "pywrapfst.pyx":1661
  *     return _init_FstSymbolTable(syms, self._fst)
  * 
  *   cpdef uint64 properties(self, uint64 mask, bool test):             # <<<<<<<<<<<<<<
@@ -20582,74 +19648,90 @@ static __pyx_t_10basictypes_uint64 __pyx_f_9pywrapfst_4_Fst_properties(struct __
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_properties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1637, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_33properties)) {
-      __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_mask); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1637, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_test); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1637, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
-      __pyx_t_7 = 0;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
-        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
-        if (likely(__pyx_t_6)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-          __Pyx_INCREF(__pyx_t_6);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_5, function);
-          __pyx_t_7 = 1;
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_properties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1661, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_33properties)) {
+        __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_mask); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1661, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_test); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1661, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
+        __pyx_t_7 = 0;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
+          __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+          if (likely(__pyx_t_6)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+            __Pyx_INCREF(__pyx_t_6);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_5, function);
+            __pyx_t_7 = 1;
+          }
+        }
+        #if CYTHON_FAST_PYCALL
+        if (PyFunction_Check(__pyx_t_5)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
+          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1661, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        } else
+        #endif
+        #if CYTHON_FAST_PYCCALL
+        if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
+          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1661, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        } else
+        #endif
+        {
+          __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1661, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_8);
+          if (__pyx_t_6) {
+            __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
+          }
+          __Pyx_GIVEREF(__pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_3);
+          __Pyx_GIVEREF(__pyx_t_4);
+          PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_4);
+          __pyx_t_3 = 0;
+          __pyx_t_4 = 0;
+          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1661, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
         }
+        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+        __pyx_t_9 = __Pyx_PyInt_As_uint64_t(__pyx_t_2); if (unlikely((__pyx_t_9 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1661, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_9;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1637, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
       #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1637, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1637, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        if (__pyx_t_6) {
-          __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        }
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_3);
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_4);
-        __pyx_t_3 = 0;
-        __pyx_t_4 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1637, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_9 = __Pyx_PyInt_As_uint64_t(__pyx_t_2); if (unlikely((__pyx_t_9 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1637, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_9;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1655
+  /* "pywrapfst.pyx":1679
  *       A 64-bit bitmask representing the requested properties.
  *     """
  *     return self._fst.get().Properties(mask, test)             # <<<<<<<<<<<<<<
@@ -20658,12 +19740,12 @@ static __pyx_t_10basictypes_uint64 __pyx_f_9pywrapfst_4_Fst_properties(struct __
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1655, __pyx_L1_error)
+    __PYX_ERR(0, 1679, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_fst.get()->Properties(__pyx_v_mask, __pyx_v_test);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1637
+  /* "pywrapfst.pyx":1661
  *     return _init_FstSymbolTable(syms, self._fst)
  * 
  *   cpdef uint64 properties(self, uint64 mask, bool test):             # <<<<<<<<<<<<<<
@@ -20719,11 +19801,11 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_33properties(PyObject *__pyx_v_self,
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_test)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("properties", 1, 2, 2, 1); __PYX_ERR(0, 1637, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("properties", 1, 2, 2, 1); __PYX_ERR(0, 1661, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "properties") < 0)) __PYX_ERR(0, 1637, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "properties") < 0)) __PYX_ERR(0, 1661, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -20731,12 +19813,12 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_33properties(PyObject *__pyx_v_self,
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __pyx_v_mask = __Pyx_PyInt_As_uint64_t(values[0]); if (unlikely((__pyx_v_mask == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1637, __pyx_L3_error)
-    __pyx_v_test = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_test == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1637, __pyx_L3_error)
+    __pyx_v_mask = __Pyx_PyInt_As_uint64_t(values[0]); if (unlikely((__pyx_v_mask == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1661, __pyx_L3_error)
+    __pyx_v_test = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_test == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1661, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("properties", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1637, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("properties", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1661, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._Fst.properties", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -20755,7 +19837,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_32properties(struct __pyx_obj_9pywrap
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("properties", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(__pyx_f_9pywrapfst_4_Fst_properties(__pyx_v_self, __pyx_v_mask, __pyx_v_test, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1637, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(__pyx_f_9pywrapfst_4_Fst_properties(__pyx_v_self, __pyx_v_mask, __pyx_v_test, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1661, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -20772,7 +19854,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_32properties(struct __pyx_obj_9pywrap
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1657
+/* "pywrapfst.pyx":1681
  *     return self._fst.get().Properties(mask, test)
  * 
  *   cpdef int64 start(self):             # <<<<<<<<<<<<<<
@@ -20793,39 +19875,52 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_4_Fst_start(struct __pyx_ob
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_start); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1657, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_35start)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_start); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1681, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_35start)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1681, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1681, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1657, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1657, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1657, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1663
+  /* "pywrapfst.pyx":1687
  *     Returns the start state.
  *     """
  *     return self._fst.get().Start()             # <<<<<<<<<<<<<<
@@ -20834,12 +19929,12 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_4_Fst_start(struct __pyx_ob
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1663, __pyx_L1_error)
+    __PYX_ERR(0, 1687, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_fst.get()->Start();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1657
+  /* "pywrapfst.pyx":1681
  *     return self._fst.get().Properties(mask, test)
  * 
  *   cpdef int64 start(self):             # <<<<<<<<<<<<<<
@@ -20880,7 +19975,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_34start(struct __pyx_obj_9pywrapfst__
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("start", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_4_Fst_start(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1657, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_4_Fst_start(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1681, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -20897,7 +19992,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_34start(struct __pyx_obj_9pywrapfst__
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1665
+/* "pywrapfst.pyx":1689
  *     return self._fst.get().Start()
  * 
  *   cpdef StateIterator states(self):             # <<<<<<<<<<<<<<
@@ -20917,40 +20012,53 @@ static struct __pyx_obj_9pywrapfst_StateIterator *__pyx_f_9pywrapfst_4_Fst_state
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_states); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1665, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_37states)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_states); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1689, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_37states)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1689, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_StateIterator))))) __PYX_ERR(0, 1689, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst_StateIterator *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1665, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1665, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_StateIterator))))) __PYX_ERR(0, 1665, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst_StateIterator *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1676
+  /* "pywrapfst.pyx":1700
  *     See also: `arcs`, `mutable_arcs`.
  *     """
  *     return StateIterator(self)             # <<<<<<<<<<<<<<
@@ -20958,13 +20066,13 @@ static struct __pyx_obj_9pywrapfst_StateIterator *__pyx_f_9pywrapfst_4_Fst_state
  *   cpdef string text(self, _SymbolTable isymbols=None,
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_1 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_9pywrapfst_StateIterator), ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1676, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_9pywrapfst_StateIterator), ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1700, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst_StateIterator *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1665
+  /* "pywrapfst.pyx":1689
  *     return self._fst.get().Start()
  * 
  *   cpdef StateIterator states(self):             # <<<<<<<<<<<<<<
@@ -21006,7 +20114,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_36states(struct __pyx_obj_9pywrapfst_
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("states", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_states(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1665, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_4_Fst_states(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1689, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -21023,7 +20131,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_36states(struct __pyx_obj_9pywrapfst_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1678
+/* "pywrapfst.pyx":1702
  *     return StateIterator(self)
  * 
  *   cpdef string text(self, _SymbolTable isymbols=None,             # <<<<<<<<<<<<<<
@@ -21035,7 +20143,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_39text(PyObject *__pyx_v_self, PyObje
 static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_4_Fst_text *__pyx_optional_args) {
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_isymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-  /* "pywrapfst.pyx":1679
+  /* "pywrapfst.pyx":1703
  * 
  *   cpdef string text(self, _SymbolTable isymbols=None,
  *       _SymbolTable osymbols=None, _SymbolTable ssymbols=None,             # <<<<<<<<<<<<<<
@@ -21045,7 +20153,7 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_osymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_ssymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-  /* "pywrapfst.pyx":1680
+  /* "pywrapfst.pyx":1704
  *   cpdef string text(self, _SymbolTable isymbols=None,
  *       _SymbolTable osymbols=None, _SymbolTable ssymbols=None,
  *       bool acceptor=False, bool show_weight_one=False, missing_sym=b""):             # <<<<<<<<<<<<<<
@@ -21054,7 +20162,7 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
  */
   bool __pyx_v_acceptor = ((bool)0);
   bool __pyx_v_show_weight_one = ((bool)0);
-  PyObject *__pyx_v_missing_sym = ((PyObject *)__pyx_kp_b__24);
+  PyObject *__pyx_v_missing_sym = ((PyObject *)__pyx_kp_b__10);
   fst::SymbolTable *__pyx_v_ssymbols_ptr;
   std::stringstream __pyx_v_sstrm;
   std::string __pyx_r;
@@ -21095,7 +20203,7 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
     }
   }
 
-  /* "pywrapfst.pyx":1678
+  /* "pywrapfst.pyx":1702
  *     return StateIterator(self)
  * 
  *   cpdef string text(self, _SymbolTable isymbols=None,             # <<<<<<<<<<<<<<
@@ -21105,86 +20213,102 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_text); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1678, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_39text)) {
-      __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_v_acceptor); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1678, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_show_weight_one); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1678, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
-      __pyx_t_7 = 0;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
-        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
-        if (likely(__pyx_t_6)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-          __Pyx_INCREF(__pyx_t_6);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_5, function);
-          __pyx_t_7 = 1;
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_text); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1702, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_39text)) {
+        __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_v_acceptor); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1702, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_show_weight_one); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1702, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
+        __pyx_t_7 = 0;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
+          __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+          if (likely(__pyx_t_6)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+            __Pyx_INCREF(__pyx_t_6);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_5, function);
+            __pyx_t_7 = 1;
+          }
         }
+        #if CYTHON_FAST_PYCALL
+        if (PyFunction_Check(__pyx_t_5)) {
+          PyObject *__pyx_temp[7] = {__pyx_t_6, ((PyObject *)__pyx_v_isymbols), ((PyObject *)__pyx_v_osymbols), ((PyObject *)__pyx_v_ssymbols), __pyx_t_3, __pyx_t_4, __pyx_v_missing_sym};
+          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 6+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1702, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        } else
+        #endif
+        #if CYTHON_FAST_PYCCALL
+        if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
+          PyObject *__pyx_temp[7] = {__pyx_t_6, ((PyObject *)__pyx_v_isymbols), ((PyObject *)__pyx_v_osymbols), ((PyObject *)__pyx_v_ssymbols), __pyx_t_3, __pyx_t_4, __pyx_v_missing_sym};
+          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 6+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1702, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        } else
+        #endif
+        {
+          __pyx_t_8 = PyTuple_New(6+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1702, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_8);
+          if (__pyx_t_6) {
+            __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
+          }
+          __Pyx_INCREF(((PyObject *)__pyx_v_isymbols));
+          __Pyx_GIVEREF(((PyObject *)__pyx_v_isymbols));
+          PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, ((PyObject *)__pyx_v_isymbols));
+          __Pyx_INCREF(((PyObject *)__pyx_v_osymbols));
+          __Pyx_GIVEREF(((PyObject *)__pyx_v_osymbols));
+          PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, ((PyObject *)__pyx_v_osymbols));
+          __Pyx_INCREF(((PyObject *)__pyx_v_ssymbols));
+          __Pyx_GIVEREF(((PyObject *)__pyx_v_ssymbols));
+          PyTuple_SET_ITEM(__pyx_t_8, 2+__pyx_t_7, ((PyObject *)__pyx_v_ssymbols));
+          __Pyx_GIVEREF(__pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_8, 3+__pyx_t_7, __pyx_t_3);
+          __Pyx_GIVEREF(__pyx_t_4);
+          PyTuple_SET_ITEM(__pyx_t_8, 4+__pyx_t_7, __pyx_t_4);
+          __Pyx_INCREF(__pyx_v_missing_sym);
+          __Pyx_GIVEREF(__pyx_v_missing_sym);
+          PyTuple_SET_ITEM(__pyx_t_8, 5+__pyx_t_7, __pyx_v_missing_sym);
+          __pyx_t_3 = 0;
+          __pyx_t_4 = 0;
+          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1702, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+        }
+        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+        __pyx_t_9 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1702, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_9;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[7] = {__pyx_t_6, ((PyObject *)__pyx_v_isymbols), ((PyObject *)__pyx_v_osymbols), ((PyObject *)__pyx_v_ssymbols), __pyx_t_3, __pyx_t_4, __pyx_v_missing_sym};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 6+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1678, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[7] = {__pyx_t_6, ((PyObject *)__pyx_v_isymbols), ((PyObject *)__pyx_v_osymbols), ((PyObject *)__pyx_v_ssymbols), __pyx_t_3, __pyx_t_4, __pyx_v_missing_sym};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 6+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1678, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
       #endif
-      {
-        __pyx_t_8 = PyTuple_New(6+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1678, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        if (__pyx_t_6) {
-          __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        }
-        __Pyx_INCREF(((PyObject *)__pyx_v_isymbols));
-        __Pyx_GIVEREF(((PyObject *)__pyx_v_isymbols));
-        PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, ((PyObject *)__pyx_v_isymbols));
-        __Pyx_INCREF(((PyObject *)__pyx_v_osymbols));
-        __Pyx_GIVEREF(((PyObject *)__pyx_v_osymbols));
-        PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, ((PyObject *)__pyx_v_osymbols));
-        __Pyx_INCREF(((PyObject *)__pyx_v_ssymbols));
-        __Pyx_GIVEREF(((PyObject *)__pyx_v_ssymbols));
-        PyTuple_SET_ITEM(__pyx_t_8, 2+__pyx_t_7, ((PyObject *)__pyx_v_ssymbols));
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_8, 3+__pyx_t_7, __pyx_t_3);
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_8, 4+__pyx_t_7, __pyx_t_4);
-        __Pyx_INCREF(__pyx_v_missing_sym);
-        __Pyx_GIVEREF(__pyx_v_missing_sym);
-        PyTuple_SET_ITEM(__pyx_t_8, 5+__pyx_t_7, __pyx_v_missing_sym);
-        __pyx_t_3 = 0;
-        __pyx_t_4 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1678, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_9 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1678, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_9;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1703
+  /* "pywrapfst.pyx":1727
  *     """
  *     # Prints FST to stringstream, then returns resulting string.
  *     cdef fst.SymbolTable *ssymbols_ptr = NULL             # <<<<<<<<<<<<<<
@@ -21193,7 +20317,7 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
  */
   __pyx_v_ssymbols_ptr = NULL;
 
-  /* "pywrapfst.pyx":1704
+  /* "pywrapfst.pyx":1728
  *     # Prints FST to stringstream, then returns resulting string.
  *     cdef fst.SymbolTable *ssymbols_ptr = NULL
  *     if ssymbols is not None:             # <<<<<<<<<<<<<<
@@ -21204,7 +20328,7 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
   __pyx_t_11 = (__pyx_t_10 != 0);
   if (__pyx_t_11) {
 
-    /* "pywrapfst.pyx":1705
+    /* "pywrapfst.pyx":1729
  *     cdef fst.SymbolTable *ssymbols_ptr = NULL
  *     if ssymbols is not None:
  *       ssymbols_ptr = ssymbols._table             # <<<<<<<<<<<<<<
@@ -21213,12 +20337,12 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
  */
     if (unlikely(((PyObject *)__pyx_v_ssymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 1705, __pyx_L1_error)
+      __PYX_ERR(0, 1729, __pyx_L1_error)
     }
     __pyx_t_12 = __pyx_v_ssymbols->_table;
     __pyx_v_ssymbols_ptr = __pyx_t_12;
 
-    /* "pywrapfst.pyx":1704
+    /* "pywrapfst.pyx":1728
  *     # Prints FST to stringstream, then returns resulting string.
  *     cdef fst.SymbolTable *ssymbols_ptr = NULL
  *     if ssymbols is not None:             # <<<<<<<<<<<<<<
@@ -21227,7 +20351,7 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
  */
   }
 
-  /* "pywrapfst.pyx":1707
+  /* "pywrapfst.pyx":1731
  *       ssymbols_ptr = ssymbols._table
  *     cdef stringstream sstrm
  *     fst.PrintFst(deref(self._fst), sstrm, b"<pywrapfst>",             # <<<<<<<<<<<<<<
@@ -21236,10 +20360,10 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1707, __pyx_L1_error)
+    __PYX_ERR(0, 1731, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":1708
+  /* "pywrapfst.pyx":1732
  *     cdef stringstream sstrm
  *     fst.PrintFst(deref(self._fst), sstrm, b"<pywrapfst>",
  *         self._fst.get().InputSymbols() if isymbols is None             # <<<<<<<<<<<<<<
@@ -21250,12 +20374,12 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
   if ((__pyx_t_11 != 0)) {
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-      __PYX_ERR(0, 1708, __pyx_L1_error)
+      __PYX_ERR(0, 1732, __pyx_L1_error)
     }
     __pyx_t_13 = __pyx_v_self->_fst.get()->InputSymbols();
   } else {
 
-    /* "pywrapfst.pyx":1709
+    /* "pywrapfst.pyx":1733
  *     fst.PrintFst(deref(self._fst), sstrm, b"<pywrapfst>",
  *         self._fst.get().InputSymbols() if isymbols is None
  *         else isymbols._table,             # <<<<<<<<<<<<<<
@@ -21264,12 +20388,12 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
  */
     if (unlikely(((PyObject *)__pyx_v_isymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 1709, __pyx_L1_error)
+      __PYX_ERR(0, 1733, __pyx_L1_error)
     }
     __pyx_t_13 = __pyx_v_isymbols->_table;
   }
 
-  /* "pywrapfst.pyx":1710
+  /* "pywrapfst.pyx":1734
  *         self._fst.get().InputSymbols() if isymbols is None
  *         else isymbols._table,
  *         self._fst.get().OutputSymbols() if osymbols is None             # <<<<<<<<<<<<<<
@@ -21280,12 +20404,12 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
   if ((__pyx_t_11 != 0)) {
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-      __PYX_ERR(0, 1710, __pyx_L1_error)
+      __PYX_ERR(0, 1734, __pyx_L1_error)
     }
     __pyx_t_14 = __pyx_v_self->_fst.get()->OutputSymbols();
   } else {
 
-    /* "pywrapfst.pyx":1711
+    /* "pywrapfst.pyx":1735
  *         else isymbols._table,
  *         self._fst.get().OutputSymbols() if osymbols is None
  *         else osymbols._table,             # <<<<<<<<<<<<<<
@@ -21294,21 +20418,21 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
  */
     if (unlikely(((PyObject *)__pyx_v_osymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 1711, __pyx_L1_error)
+      __PYX_ERR(0, 1735, __pyx_L1_error)
     }
     __pyx_t_14 = __pyx_v_osymbols->_table;
   }
 
-  /* "pywrapfst.pyx":1712
+  /* "pywrapfst.pyx":1736
  *         self._fst.get().OutputSymbols() if osymbols is None
  *         else osymbols._table,
  *         ssymbols_ptr, acceptor, show_weight_one, tostring(missing_sym))             # <<<<<<<<<<<<<<
  *     return sstrm.str()
  * 
  */
-  __pyx_t_9 = __pyx_f_9pywrapfst_tostring(__pyx_v_missing_sym, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1712, __pyx_L1_error)
+  __pyx_t_9 = __pyx_f_9pywrapfst_tostring(__pyx_v_missing_sym, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1736, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1707
+  /* "pywrapfst.pyx":1731
  *       ssymbols_ptr = ssymbols._table
  *     cdef stringstream sstrm
  *     fst.PrintFst(deref(self._fst), sstrm, b"<pywrapfst>",             # <<<<<<<<<<<<<<
@@ -21317,7 +20441,7 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
  */
   fst::script::PrintFst((*__pyx_v_self->_fst), __pyx_v_sstrm, __pyx_k_pywrapfst, __pyx_t_13, __pyx_t_14, __pyx_v_ssymbols_ptr, __pyx_v_acceptor, __pyx_v_show_weight_one, __pyx_t_9);
 
-  /* "pywrapfst.pyx":1713
+  /* "pywrapfst.pyx":1737
  *         else osymbols._table,
  *         ssymbols_ptr, acceptor, show_weight_one, tostring(missing_sym))
  *     return sstrm.str()             # <<<<<<<<<<<<<<
@@ -21327,7 +20451,7 @@ static std::string __pyx_f_9pywrapfst_4_Fst_text(struct __pyx_obj_9pywrapfst__Fs
   __pyx_r = __pyx_v_sstrm.str();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1678
+  /* "pywrapfst.pyx":1702
  *     return StateIterator(self)
  * 
  *   cpdef string text(self, _SymbolTable isymbols=None,             # <<<<<<<<<<<<<<
@@ -21369,7 +20493,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_39text(PyObject *__pyx_v_self, PyObje
     PyObject* values[6] = {0,0,0,0,0,0};
     values[0] = (PyObject *)((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-    /* "pywrapfst.pyx":1679
+    /* "pywrapfst.pyx":1703
  * 
  *   cpdef string text(self, _SymbolTable isymbols=None,
  *       _SymbolTable osymbols=None, _SymbolTable ssymbols=None,             # <<<<<<<<<<<<<<
@@ -21378,7 +20502,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_39text(PyObject *__pyx_v_self, PyObje
  */
     values[1] = (PyObject *)((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
     values[2] = (PyObject *)((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
-    values[5] = ((PyObject *)__pyx_kp_b__24);
+    values[5] = ((PyObject *)__pyx_kp_b__10);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
@@ -21437,7 +20561,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_39text(PyObject *__pyx_v_self, PyObje
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "text") < 0)) __PYX_ERR(0, 1678, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "text") < 0)) __PYX_ERR(0, 1702, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -21461,10 +20585,10 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_39text(PyObject *__pyx_v_self, PyObje
     __pyx_v_osymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)values[1]);
     __pyx_v_ssymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)values[2]);
     if (values[3]) {
-      __pyx_v_acceptor = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_acceptor == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1680, __pyx_L3_error)
+      __pyx_v_acceptor = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_acceptor == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1704, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":1680
+      /* "pywrapfst.pyx":1704
  *   cpdef string text(self, _SymbolTable isymbols=None,
  *       _SymbolTable osymbols=None, _SymbolTable ssymbols=None,
  *       bool acceptor=False, bool show_weight_one=False, missing_sym=b""):             # <<<<<<<<<<<<<<
@@ -21474,7 +20598,7 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_39text(PyObject *__pyx_v_self, PyObje
       __pyx_v_acceptor = ((bool)0);
     }
     if (values[4]) {
-      __pyx_v_show_weight_one = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_show_weight_one == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1680, __pyx_L3_error)
+      __pyx_v_show_weight_one = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_show_weight_one == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1704, __pyx_L3_error)
     } else {
       __pyx_v_show_weight_one = ((bool)0);
     }
@@ -21482,18 +20606,18 @@ static PyObject *__pyx_pw_9pywrapfst_4_Fst_39text(PyObject *__pyx_v_self, PyObje
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("text", 0, 0, 6, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1678, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("text", 0, 0, 6, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1702, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._Fst.text", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_isymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "isymbols", 0))) __PYX_ERR(0, 1678, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_osymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "osymbols", 0))) __PYX_ERR(0, 1679, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ssymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "ssymbols", 0))) __PYX_ERR(0, 1679, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_isymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "isymbols", 0))) __PYX_ERR(0, 1702, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_osymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "osymbols", 0))) __PYX_ERR(0, 1703, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ssymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "ssymbols", 0))) __PYX_ERR(0, 1703, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_4_Fst_38text(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), __pyx_v_isymbols, __pyx_v_osymbols, __pyx_v_ssymbols, __pyx_v_acceptor, __pyx_v_show_weight_one, __pyx_v_missing_sym);
 
-  /* "pywrapfst.pyx":1678
+  /* "pywrapfst.pyx":1702
  *     return StateIterator(self)
  * 
  *   cpdef string text(self, _SymbolTable isymbols=None,             # <<<<<<<<<<<<<<
@@ -21526,7 +20650,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_38text(struct __pyx_obj_9pywrapfst__F
   __pyx_t_2.show_weight_one = __pyx_v_show_weight_one;
   __pyx_t_2.missing_sym = __pyx_v_missing_sym;
   __pyx_t_1 = __pyx_vtabptr_9pywrapfst__Fst->text(__pyx_v_self, 1, &__pyx_t_2); 
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1678, __pyx_L1_error)
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1702, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
@@ -21543,7 +20667,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_38text(struct __pyx_obj_9pywrapfst__F
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1715
+/* "pywrapfst.pyx":1739
  *     return sstrm.str()
  * 
  *   cpdef bool verify(self):             # <<<<<<<<<<<<<<
@@ -21564,39 +20688,52 @@ static bool __pyx_f_9pywrapfst_4_Fst_verify(struct __pyx_obj_9pywrapfst__Fst *__
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_verify); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1715, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_41verify)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_verify); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1739, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_41verify)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1739, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1739, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1715, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1715, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1715, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1724
+  /* "pywrapfst.pyx":1748
  *       True if the contents are sane, False otherwise.
  *     """
  *     return fst.Verify(deref(self._fst))             # <<<<<<<<<<<<<<
@@ -21605,12 +20742,12 @@ static bool __pyx_f_9pywrapfst_4_Fst_verify(struct __pyx_obj_9pywrapfst__Fst *__
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1724, __pyx_L1_error)
+    __PYX_ERR(0, 1748, __pyx_L1_error)
   }
   __pyx_r = fst::script::Verify((*__pyx_v_self->_fst));
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1715
+  /* "pywrapfst.pyx":1739
  *     return sstrm.str()
  * 
  *   cpdef bool verify(self):             # <<<<<<<<<<<<<<
@@ -21651,7 +20788,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_40verify(struct __pyx_obj_9pywrapfst_
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("verify", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_4_Fst_verify(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1715, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_4_Fst_verify(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1739, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -21668,7 +20805,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_40verify(struct __pyx_obj_9pywrapfst_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1726
+/* "pywrapfst.pyx":1750
  *     return fst.Verify(deref(self._fst))
  * 
  *   cpdef string weight_type(self):             # <<<<<<<<<<<<<<
@@ -21689,39 +20826,52 @@ static std::string __pyx_f_9pywrapfst_4_Fst_weight_type(struct __pyx_obj_9pywrap
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_weight_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1726, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_43weight_type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_weight_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1750, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_43weight_type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1750, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1750, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1726, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1726, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1726, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1735
+  /* "pywrapfst.pyx":1759
  *       A string representing the weight type.
  *     """
  *     return self._fst.get().WeightType()             # <<<<<<<<<<<<<<
@@ -21730,12 +20880,12 @@ static std::string __pyx_f_9pywrapfst_4_Fst_weight_type(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1735, __pyx_L1_error)
+    __PYX_ERR(0, 1759, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_fst.get()->WeightType();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1726
+  /* "pywrapfst.pyx":1750
  *     return fst.Verify(deref(self._fst))
  * 
  *   cpdef string weight_type(self):             # <<<<<<<<<<<<<<
@@ -21776,7 +20926,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_42weight_type(struct __pyx_obj_9pywra
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("weight_type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_4_Fst_weight_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1726, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_4_Fst_weight_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1750, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -21793,7 +20943,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_42weight_type(struct __pyx_obj_9pywra
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1737
+/* "pywrapfst.pyx":1761
  *     return self._fst.get().WeightType()
  * 
  *   cpdef void write(self, filename) except *:             # <<<<<<<<<<<<<<
@@ -21808,70 +20958,57 @@ static void __pyx_f_9pywrapfst_4_Fst_write(struct __pyx_obj_9pywrapfst__Fst *__p
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  std::string __pyx_t_6;
-  int __pyx_t_7;
-  PyObject *__pyx_t_8 = NULL;
+  std::string __pyx_t_5;
+  int __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("write", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1737, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_45write)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1761, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_45write)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_filename); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1737, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_filename);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1761, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1737, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1737, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1737, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(__pyx_v_filename);
-          __Pyx_GIVEREF(__pyx_v_filename);
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_v_filename);
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1737, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1751
+  /* "pywrapfst.pyx":1775
  *       FstIOError: Write failed.
  *     """
  *     if not self._fst.get().Write(tostring(filename)):             # <<<<<<<<<<<<<<
@@ -21880,117 +21017,59 @@ static void __pyx_f_9pywrapfst_4_Fst_write(struct __pyx_obj_9pywrapfst__Fst *__p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1751, __pyx_L1_error)
+    __PYX_ERR(0, 1775, __pyx_L1_error)
   }
-  __pyx_t_6 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1751, __pyx_L1_error)
-  __pyx_t_7 = ((!(__pyx_v_self->_fst.get()->Write(__pyx_t_6) != 0)) != 0);
-  if (unlikely(__pyx_t_7)) {
+  __pyx_t_5 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1775, __pyx_L1_error)
+  __pyx_t_6 = ((!(__pyx_v_self->_fst.get()->Write(__pyx_t_5) != 0)) != 0);
+  if (unlikely(__pyx_t_6)) {
 
-    /* "pywrapfst.pyx":1752
+    /* "pywrapfst.pyx":1776
  *     """
  *     if not self._fst.get().Write(tostring(filename)):
  *       raise FstIOError("Write failed: {!r}".format(filename))             # <<<<<<<<<<<<<<
  * 
- *   cpdef string write_to_string(self):
+ *   cpdef bytes write_to_string(self):
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1752, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1776, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Write_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1752, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_4 = NULL;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
-      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5);
-      if (likely(__pyx_t_4)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-        __Pyx_INCREF(__pyx_t_4);
+    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Write_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1776, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_7 = NULL;
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_7)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_7);
         __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_5, function);
-      }
-    }
-    if (!__pyx_t_4) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_filename); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1752, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1752, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_filename};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1752, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1752, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_4); __pyx_t_4 = NULL;
-        __Pyx_INCREF(__pyx_v_filename);
-        __Pyx_GIVEREF(__pyx_v_filename);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_filename);
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1752, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+        __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_5 = NULL;
+    __pyx_t_3 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_7, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_filename);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1776, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __pyx_t_4 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_5)) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_4)) {
         PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_4);
         __Pyx_INCREF(function);
         __Pyx_DECREF_SET(__pyx_t_2, function);
       }
     }
-    if (!__pyx_t_5) {
-      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1752, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-        __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1752, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-        __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1752, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1752, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_3);
-        __pyx_t_3 = 0;
-        __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1752, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1776, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_Raise(__pyx_t_1, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 1752, __pyx_L1_error)
+    __PYX_ERR(0, 1776, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1751
+    /* "pywrapfst.pyx":1775
  *       FstIOError: Write failed.
  *     """
  *     if not self._fst.get().Write(tostring(filename)):             # <<<<<<<<<<<<<<
@@ -21999,7 +21078,7 @@ static void __pyx_f_9pywrapfst_4_Fst_write(struct __pyx_obj_9pywrapfst__Fst *__p
  */
   }
 
-  /* "pywrapfst.pyx":1737
+  /* "pywrapfst.pyx":1761
  *     return self._fst.get().WeightType()
  * 
  *   cpdef void write(self, filename) except *:             # <<<<<<<<<<<<<<
@@ -22014,8 +21093,7 @@ static void __pyx_f_9pywrapfst_4_Fst_write(struct __pyx_obj_9pywrapfst__Fst *__p
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_AddTraceback("pywrapfst._Fst.write", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -22041,8 +21119,8 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_44write(struct __pyx_obj_9pywrapfst__
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("write", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_f_9pywrapfst_4_Fst_write(__pyx_v_self, __pyx_v_filename, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1737, __pyx_L1_error)
-  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1737, __pyx_L1_error)
+  __pyx_f_9pywrapfst_4_Fst_write(__pyx_v_self, __pyx_v_filename, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1761, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1761, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -22059,114 +21137,143 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_44write(struct __pyx_obj_9pywrapfst__
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1754
+/* "pywrapfst.pyx":1778
  *       raise FstIOError("Write failed: {!r}".format(filename))
  * 
- *   cpdef string write_to_string(self):             # <<<<<<<<<<<<<<
+ *   cpdef bytes write_to_string(self):             # <<<<<<<<<<<<<<
  *     """
  *     write_to_string(self)
  */
 
 static PyObject *__pyx_pw_9pywrapfst_4_Fst_47write_to_string(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static std::string __pyx_f_9pywrapfst_4_Fst_write_to_string(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, int __pyx_skip_dispatch) {
+static PyObject *__pyx_f_9pywrapfst_4_Fst_write_to_string(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_self, int __pyx_skip_dispatch) {
   std::stringstream __pyx_v_sstrm;
-  std::string __pyx_r;
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  std::string __pyx_t_5;
-  int __pyx_t_6;
+  int __pyx_t_5;
   __Pyx_RefNannySetupContext("write_to_string", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write_to_string); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1754, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_47write_to_string)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write_to_string); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1778, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_4_Fst_47write_to_string)) {
+        __Pyx_XDECREF(__pyx_r);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1778, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(PyBytes_CheckExact(__pyx_t_2))||((__pyx_t_2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_2)->tp_name), 0))) __PYX_ERR(0, 1778, __pyx_L1_error)
+        __pyx_r = ((PyObject*)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1754, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1754, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1754, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1769
+  /* "pywrapfst.pyx":1793
  *     """
  *     cdef stringstream sstrm
- *     if not self._fst.get().Write(sstrm, "write_to_string"):             # <<<<<<<<<<<<<<
+ *     if not self._fst.get().Write(sstrm, b"<pywrapfst>"):             # <<<<<<<<<<<<<<
  *       raise FstIOError("Write to string failed")
  *     return sstrm.str()
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1769, __pyx_L1_error)
+    __PYX_ERR(0, 1793, __pyx_L1_error)
   }
-  __pyx_t_6 = ((!(__pyx_v_self->_fst.get()->Write(__pyx_v_sstrm, __pyx_k_write_to_string) != 0)) != 0);
-  if (unlikely(__pyx_t_6)) {
+  __pyx_t_5 = ((!(__pyx_v_self->_fst.get()->Write(__pyx_v_sstrm, __pyx_k_pywrapfst) != 0)) != 0);
+  if (unlikely(__pyx_t_5)) {
 
-    /* "pywrapfst.pyx":1770
+    /* "pywrapfst.pyx":1794
  *     cdef stringstream sstrm
- *     if not self._fst.get().Write(sstrm, "write_to_string"):
+ *     if not self._fst.get().Write(sstrm, b"<pywrapfst>"):
  *       raise FstIOError("Write to string failed")             # <<<<<<<<<<<<<<
  *     return sstrm.str()
  * 
  */
-    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1770, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__29, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1770, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1794, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __pyx_t_3 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_3)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_kp_u_Write_to_string_failed) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_kp_u_Write_to_string_failed);
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1794, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 1770, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 1794, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1769
+    /* "pywrapfst.pyx":1793
  *     """
  *     cdef stringstream sstrm
- *     if not self._fst.get().Write(sstrm, "write_to_string"):             # <<<<<<<<<<<<<<
+ *     if not self._fst.get().Write(sstrm, b"<pywrapfst>"):             # <<<<<<<<<<<<<<
  *       raise FstIOError("Write to string failed")
  *     return sstrm.str()
  */
   }
 
-  /* "pywrapfst.pyx":1771
- *     if not self._fst.get().Write(sstrm, "write_to_string"):
+  /* "pywrapfst.pyx":1795
+ *     if not self._fst.get().Write(sstrm, b"<pywrapfst>"):
  *       raise FstIOError("Write to string failed")
  *     return sstrm.str()             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_r = __pyx_v_sstrm.str();
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_sstrm.str()); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1795, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1754
+  /* "pywrapfst.pyx":1778
  *       raise FstIOError("Write failed: {!r}".format(filename))
  * 
- *   cpdef string write_to_string(self):             # <<<<<<<<<<<<<<
+ *   cpdef bytes write_to_string(self):             # <<<<<<<<<<<<<<
  *     """
  *     write_to_string(self)
  */
@@ -22177,16 +21284,17 @@ static std::string __pyx_f_9pywrapfst_4_Fst_write_to_string(struct __pyx_obj_9py
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_WriteUnraisable("pywrapfst._Fst.write_to_string", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
-  __Pyx_pretend_to_initialize(&__pyx_r);
+  __Pyx_AddTraceback("pywrapfst._Fst.write_to_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
   __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
 static PyObject *__pyx_pw_9pywrapfst_4_Fst_47write_to_string(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9pywrapfst_4_Fst_46write_to_string[] = "\n    write_to_string(self)\n\n    Serializes FST to a string.\n\n    Returns:\n      A string.\n\n    Raises:\n      FstIOError: Write to string failed.\n\n    See also: `read_from_string`.\n    ";
+static char __pyx_doc_9pywrapfst_4_Fst_46write_to_string[] = "\n    write_to_string(self)\n\n    Serializes FST to a string.\n\n    Returns:\n      A bytestring.\n\n    Raises:\n      FstIOError: Write to string failed.\n\n    See also: `read_from_string`.\n    ";
 static PyObject *__pyx_pw_9pywrapfst_4_Fst_47write_to_string(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
@@ -22204,7 +21312,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_46write_to_string(struct __pyx_obj_9p
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("write_to_string", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_4_Fst_write_to_string(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1754, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_4_Fst_write_to_string(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1778, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -22221,7 +21329,7 @@ static PyObject *__pyx_pf_9pywrapfst_4_Fst_46write_to_string(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1784
+/* "pywrapfst.pyx":1808
  *   """
  * 
  *   cdef void _check_mutating_imethod(self) except *:             # <<<<<<<<<<<<<<
@@ -22234,9 +21342,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__check_mutating_imethod(struct __py
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("_check_mutating_imethod", 0);
 
-  /* "pywrapfst.pyx":1789
+  /* "pywrapfst.pyx":1813
  *     This function is not visible to Python users.
  *     """
  *     if self._fst.get().Properties(fst.kError, True) == fst.kError:             # <<<<<<<<<<<<<<
@@ -22245,28 +21354,40 @@ static void __pyx_f_9pywrapfst_11_MutableFst__check_mutating_imethod(struct __py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1789, __pyx_L1_error)
+    __PYX_ERR(0, 1813, __pyx_L1_error)
   }
   __pyx_t_1 = ((__pyx_v_self->__pyx_base._fst.get()->Properties(fst::kError, 1) == fst::kError) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":1790
+    /* "pywrapfst.pyx":1814
  *     """
  *     if self._fst.get().Properties(fst.kError, True) == fst.kError:
  *       raise FstOpError("Operation failed")             # <<<<<<<<<<<<<<
  * 
  *   cdef void _add_arc(self, int64 state, Arc arc) except *:
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1790, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__30, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1790, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1814, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_Operation_failed) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_Operation_failed);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1814, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 1790, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 1814, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1789
+    /* "pywrapfst.pyx":1813
  *     This function is not visible to Python users.
  *     """
  *     if self._fst.get().Properties(fst.kError, True) == fst.kError:             # <<<<<<<<<<<<<<
@@ -22275,7 +21396,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__check_mutating_imethod(struct __py
  */
   }
 
-  /* "pywrapfst.pyx":1784
+  /* "pywrapfst.pyx":1808
  *   """
  * 
  *   cdef void _check_mutating_imethod(self) except *:             # <<<<<<<<<<<<<<
@@ -22288,12 +21409,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__check_mutating_imethod(struct __py
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst._MutableFst._check_mutating_imethod", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":1792
+/* "pywrapfst.pyx":1816
  *       raise FstOpError("Operation failed")
  * 
  *   cdef void _add_arc(self, int64 state, Arc arc) except *:             # <<<<<<<<<<<<<<
@@ -22306,9 +21428,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__add_arc(struct __pyx_obj_9pywrapfs
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("_add_arc", 0);
 
-  /* "pywrapfst.pyx":1793
+  /* "pywrapfst.pyx":1817
  * 
  *   cdef void _add_arc(self, int64 state, Arc arc) except *:
  *     if not self._fst.get().ValidStateId(state):             # <<<<<<<<<<<<<<
@@ -22317,28 +21440,40 @@ static void __pyx_f_9pywrapfst_11_MutableFst__add_arc(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1793, __pyx_L1_error)
+    __PYX_ERR(0, 1817, __pyx_L1_error)
   }
   __pyx_t_1 = ((!(__pyx_v_self->__pyx_base._fst.get()->ValidStateId(__pyx_v_state) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":1794
+    /* "pywrapfst.pyx":1818
  *   cdef void _add_arc(self, int64 state, Arc arc) except *:
  *     if not self._fst.get().ValidStateId(state):
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     if not self._mfst.get().AddArc(state, deref(arc._arc)):
  *       raise FstOpError("Incompatible or invalid weight type")
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1794, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__31, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1794, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1818, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1818, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 1794, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 1818, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1793
+    /* "pywrapfst.pyx":1817
  * 
  *   cdef void _add_arc(self, int64 state, Arc arc) except *:
  *     if not self._fst.get().ValidStateId(state):             # <<<<<<<<<<<<<<
@@ -22347,7 +21482,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__add_arc(struct __pyx_obj_9pywrapfs
  */
   }
 
-  /* "pywrapfst.pyx":1795
+  /* "pywrapfst.pyx":1819
  *     if not self._fst.get().ValidStateId(state):
  *       raise FstIndexError("State index out of range")
  *     if not self._mfst.get().AddArc(state, deref(arc._arc)):             # <<<<<<<<<<<<<<
@@ -22356,32 +21491,44 @@ static void __pyx_f_9pywrapfst_11_MutableFst__add_arc(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 1795, __pyx_L1_error)
+    __PYX_ERR(0, 1819, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_arc) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 1795, __pyx_L1_error)
+    __PYX_ERR(0, 1819, __pyx_L1_error)
   }
   __pyx_t_1 = ((!(__pyx_v_self->_mfst.get()->AddArc(__pyx_v_state, (*__pyx_v_arc->_arc)) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":1796
+    /* "pywrapfst.pyx":1820
  *       raise FstIndexError("State index out of range")
  *     if not self._mfst.get().AddArc(state, deref(arc._arc)):
  *       raise FstOpError("Incompatible or invalid weight type")             # <<<<<<<<<<<<<<
  *     self._check_mutating_imethod()
  * 
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1796, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1820, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple__32, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1796, __pyx_L1_error)
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_Incompatible_or_invalid_weight_t) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_Incompatible_or_invalid_weight_t);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1820, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 1796, __pyx_L1_error)
+    __PYX_ERR(0, 1820, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1795
+    /* "pywrapfst.pyx":1819
  *     if not self._fst.get().ValidStateId(state):
  *       raise FstIndexError("State index out of range")
  *     if not self._mfst.get().AddArc(state, deref(arc._arc)):             # <<<<<<<<<<<<<<
@@ -22390,7 +21537,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__add_arc(struct __pyx_obj_9pywrapfs
  */
   }
 
-  /* "pywrapfst.pyx":1797
+  /* "pywrapfst.pyx":1821
  *     if not self._mfst.get().AddArc(state, deref(arc._arc)):
  *       raise FstOpError("Incompatible or invalid weight type")
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -22399,11 +21546,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__add_arc(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 1797, __pyx_L1_error)
+    __PYX_ERR(0, 1821, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1797, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1821, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1792
+  /* "pywrapfst.pyx":1816
  *       raise FstOpError("Operation failed")
  * 
  *   cdef void _add_arc(self, int64 state, Arc arc) except *:             # <<<<<<<<<<<<<<
@@ -22416,12 +21563,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__add_arc(struct __pyx_obj_9pywrapfs
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst._MutableFst._add_arc", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":1799
+/* "pywrapfst.pyx":1823
  *     self._check_mutating_imethod()
  * 
  *   def add_arc(self, int64 state, Arc arc):             # <<<<<<<<<<<<<<
@@ -22461,11 +21609,11 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_1add_arc(PyObject *__pyx_v_se
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_arc)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("add_arc", 1, 2, 2, 1); __PYX_ERR(0, 1799, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("add_arc", 1, 2, 2, 1); __PYX_ERR(0, 1823, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "add_arc") < 0)) __PYX_ERR(0, 1799, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "add_arc") < 0)) __PYX_ERR(0, 1823, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -22473,18 +21621,18 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_1add_arc(PyObject *__pyx_v_se
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1799, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1823, __pyx_L3_error)
     __pyx_v_arc = ((struct __pyx_obj_9pywrapfst_Arc *)values[1]);
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("add_arc", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1799, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("add_arc", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1823, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.add_arc", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_arc), __pyx_ptype_9pywrapfst_Arc, 1, "arc", 0))) __PYX_ERR(0, 1799, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_arc), __pyx_ptype_9pywrapfst_Arc, 1, "arc", 0))) __PYX_ERR(0, 1823, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_add_arc(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), __pyx_v_state, __pyx_v_arc);
 
   /* function exit code */
@@ -22501,7 +21649,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_add_arc(struct __pyx_obj_9pyw
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("add_arc", 0);
 
-  /* "pywrapfst.pyx":1818
+  /* "pywrapfst.pyx":1842
  *     See also: `add_state`.
  *     """
  *     self._add_arc(state, arc)             # <<<<<<<<<<<<<<
@@ -22510,11 +21658,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_add_arc(struct __pyx_obj_9pyw
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_add_arc");
-    __PYX_ERR(0, 1818, __pyx_L1_error)
+    __PYX_ERR(0, 1842, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_add_arc(__pyx_v_self, __pyx_v_state, __pyx_v_arc); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1818, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_add_arc(__pyx_v_self, __pyx_v_state, __pyx_v_arc); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1842, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1819
+  /* "pywrapfst.pyx":1843
  *     """
  *     self._add_arc(state, arc)
  *     return self             # <<<<<<<<<<<<<<
@@ -22526,7 +21674,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_add_arc(struct __pyx_obj_9pyw
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1799
+  /* "pywrapfst.pyx":1823
  *     self._check_mutating_imethod()
  * 
  *   def add_arc(self, int64 state, Arc arc):             # <<<<<<<<<<<<<<
@@ -22544,7 +21692,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_add_arc(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1821
+/* "pywrapfst.pyx":1845
  *     return self
  * 
  *   cpdef int64 add_state(self) except *:             # <<<<<<<<<<<<<<
@@ -22566,39 +21714,52 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_11_MutableFst_add_state(str
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_add_state); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1821, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_3add_state)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_add_state); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1845, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11_MutableFst_3add_state)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1845, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1845, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1821, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1821, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1821, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":1832
+  /* "pywrapfst.pyx":1856
  *     See also: `add_arc`, `set_start`, `set_final`.
  *     """
  *     cdef int64 result = self._mfst.get().AddState()             # <<<<<<<<<<<<<<
@@ -22607,11 +21768,11 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_11_MutableFst_add_state(str
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 1832, __pyx_L1_error)
+    __PYX_ERR(0, 1856, __pyx_L1_error)
   }
   __pyx_v_result = __pyx_v_self->_mfst.get()->AddState();
 
-  /* "pywrapfst.pyx":1833
+  /* "pywrapfst.pyx":1857
  *     """
  *     cdef int64 result = self._mfst.get().AddState()
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -22620,11 +21781,11 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_11_MutableFst_add_state(str
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 1833, __pyx_L1_error)
+    __PYX_ERR(0, 1857, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1833, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1857, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1834
+  /* "pywrapfst.pyx":1858
  *     cdef int64 result = self._mfst.get().AddState()
  *     self._check_mutating_imethod()
  *     return result             # <<<<<<<<<<<<<<
@@ -22634,7 +21795,7 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_11_MutableFst_add_state(str
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1821
+  /* "pywrapfst.pyx":1845
  *     return self
  * 
  *   cpdef int64 add_state(self) except *:             # <<<<<<<<<<<<<<
@@ -22676,8 +21837,8 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_2add_state(struct __pyx_obj_9
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("add_state", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_9pywrapfst_11_MutableFst_add_state(__pyx_v_self, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1821, __pyx_L1_error)
-  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1821, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_11_MutableFst_add_state(__pyx_v_self, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1845, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1845, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -22694,7 +21855,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_2add_state(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1836
+/* "pywrapfst.pyx":1860
  *     return result
  * 
  *   cdef void _arcsort(self, sort_type=b"ilabel") except *:             # <<<<<<<<<<<<<<
@@ -22713,7 +21874,6 @@ static void __pyx_f_9pywrapfst_11_MutableFst__arcsort(struct __pyx_obj_9pywrapfs
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_arcsort", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -22721,27 +21881,27 @@ static void __pyx_f_9pywrapfst_11_MutableFst__arcsort(struct __pyx_obj_9pywrapfs
     }
   }
 
-  /* "pywrapfst.pyx":1838
+  /* "pywrapfst.pyx":1862
  *   cdef void _arcsort(self, sort_type=b"ilabel") except *:
  *     cdef fst.ArcSortType sort_type_enum
  *     if not fst.GetArcSortType(tostring(sort_type), addr(sort_type_enum)):             # <<<<<<<<<<<<<<
  *       raise FstArgError("Unknown sort type {!r}".format(sort_type))
  *     fst.ArcSort(self._mfst.get(), sort_type_enum)
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_sort_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1838, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_sort_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1862, __pyx_L1_error)
   __pyx_t_2 = ((!(fst::script::GetArcSortType(__pyx_t_1, (&__pyx_v_sort_type_enum)) != 0)) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":1839
+    /* "pywrapfst.pyx":1863
  *     cdef fst.ArcSortType sort_type_enum
  *     if not fst.GetArcSortType(tostring(sort_type), addr(sort_type_enum)):
  *       raise FstArgError("Unknown sort type {!r}".format(sort_type))             # <<<<<<<<<<<<<<
  *     fst.ArcSort(self._mfst.get(), sort_type_enum)
  *     self._check_mutating_imethod()
  */
-    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1839, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1863, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_sort_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1839, __pyx_L1_error)
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_sort_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1863, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
@@ -22753,38 +21913,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__arcsort(struct __pyx_obj_9pywrapfs
         __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_sort_type); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1839, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_sort_type};
-        __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1839, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_sort_type};
-        __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1839, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1839, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_INCREF(__pyx_v_sort_type);
-        __Pyx_GIVEREF(__pyx_v_sort_type);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_sort_type);
-        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1839, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_v_sort_type) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_sort_type);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1863, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
@@ -22796,47 +21928,17 @@ static void __pyx_f_9pywrapfst_11_MutableFst__arcsort(struct __pyx_obj_9pywrapfs
         __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1839, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1839, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1839, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1839, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_5);
-        __pyx_t_5 = 0;
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1839, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1863, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 1839, __pyx_L1_error)
+    __PYX_ERR(0, 1863, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1838
+    /* "pywrapfst.pyx":1862
  *   cdef void _arcsort(self, sort_type=b"ilabel") except *:
  *     cdef fst.ArcSortType sort_type_enum
  *     if not fst.GetArcSortType(tostring(sort_type), addr(sort_type_enum)):             # <<<<<<<<<<<<<<
@@ -22845,7 +21947,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__arcsort(struct __pyx_obj_9pywrapfs
  */
   }
 
-  /* "pywrapfst.pyx":1840
+  /* "pywrapfst.pyx":1864
  *     if not fst.GetArcSortType(tostring(sort_type), addr(sort_type_enum)):
  *       raise FstArgError("Unknown sort type {!r}".format(sort_type))
  *     fst.ArcSort(self._mfst.get(), sort_type_enum)             # <<<<<<<<<<<<<<
@@ -22854,11 +21956,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__arcsort(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 1840, __pyx_L1_error)
+    __PYX_ERR(0, 1864, __pyx_L1_error)
   }
   fst::script::ArcSort(__pyx_v_self->_mfst.get(), __pyx_v_sort_type_enum);
 
-  /* "pywrapfst.pyx":1841
+  /* "pywrapfst.pyx":1865
  *       raise FstArgError("Unknown sort type {!r}".format(sort_type))
  *     fst.ArcSort(self._mfst.get(), sort_type_enum)
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -22867,11 +21969,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__arcsort(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 1841, __pyx_L1_error)
+    __PYX_ERR(0, 1865, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1841, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1865, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1836
+  /* "pywrapfst.pyx":1860
  *     return result
  * 
  *   cdef void _arcsort(self, sort_type=b"ilabel") except *:             # <<<<<<<<<<<<<<
@@ -22887,13 +21989,12 @@ static void __pyx_f_9pywrapfst_11_MutableFst__arcsort(struct __pyx_obj_9pywrapfs
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._MutableFst._arcsort", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":1843
+/* "pywrapfst.pyx":1867
  *     self._check_mutating_imethod()
  * 
  *   def arcsort(self, sort_type=b"ilabel"):             # <<<<<<<<<<<<<<
@@ -22903,7 +22004,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__arcsort(struct __pyx_obj_9pywrapfs
 
 /* Python wrapper */
 static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_5arcsort(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_11_MutableFst_4arcsort[] = "\n    arcsort(self, sort_type=\"ilabel\")\n\n    Sorts arcs leaving each state of the FST.\n\n    This operation destructively sorts arcs leaving each state using either\n    input or output labels.\n\n    Args:\n      sort_type: Either \"ilabel\" (sort arcs according to input labels) or\n          \"olabel\" (sort arcs according to output labels).\n\n    Returns:\n      self.\n\n    Raises:\n      FstArgError: Unknown sort type.\n\n    See also: `topsort`.\n    ";
+static char __pyx_doc_9pywrapfst_11_MutableFst_4arcsort[] = "\n    arcsort(self, sort_type=\"ilabel\")\n\n    Sorts arcs leaving each state of the FST.\n\n    This operation destructively sorts arcs leaving each state using either\n    input or output labels.\n\n    Args:\n      sort_type: Either \"ilabel\" (sort arcs according to input labels) or\n          \"olabel\" (sort arcs according to output labels).\n\n    Returns:\n      self.\n\n    Raises:\n      FstArgError: Unknown sort type.\n    ";
 static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_5arcsort(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_sort_type = 0;
   PyObject *__pyx_r = 0;
@@ -22931,7 +22032,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_5arcsort(PyObject *__pyx_v_se
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "arcsort") < 0)) __PYX_ERR(0, 1843, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "arcsort") < 0)) __PYX_ERR(0, 1867, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -22945,7 +22046,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_5arcsort(PyObject *__pyx_v_se
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("arcsort", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1843, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("arcsort", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1867, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.arcsort", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -22964,8 +22065,8 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_4arcsort(struct __pyx_obj_9py
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__arcsort __pyx_t_1;
   __Pyx_RefNannySetupContext("arcsort", 0);
 
-  /* "pywrapfst.pyx":1864
- *     See also: `topsort`.
+  /* "pywrapfst.pyx":1886
+ *       FstArgError: Unknown sort type.
  *     """
  *     self._arcsort(sort_type)             # <<<<<<<<<<<<<<
  *     return self
@@ -22973,13 +22074,13 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_4arcsort(struct __pyx_obj_9py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arcsort");
-    __PYX_ERR(0, 1864, __pyx_L1_error)
+    __PYX_ERR(0, 1886, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 1;
   __pyx_t_1.sort_type = __pyx_v_sort_type;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_arcsort(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1864, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_arcsort(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1886, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1865
+  /* "pywrapfst.pyx":1887
  *     """
  *     self._arcsort(sort_type)
  *     return self             # <<<<<<<<<<<<<<
@@ -22991,7 +22092,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_4arcsort(struct __pyx_obj_9py
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1843
+  /* "pywrapfst.pyx":1867
  *     self._check_mutating_imethod()
  * 
  *   def arcsort(self, sort_type=b"ilabel"):             # <<<<<<<<<<<<<<
@@ -23009,7 +22110,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_4arcsort(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1867
+/* "pywrapfst.pyx":1889
  *     return self
  * 
  *   cdef void _closure(self, bool closure_plus=False) except *:             # <<<<<<<<<<<<<<
@@ -23027,7 +22128,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__closure(struct __pyx_obj_9pywrapfs
     }
   }
 
-  /* "pywrapfst.pyx":1868
+  /* "pywrapfst.pyx":1890
  * 
  *   cdef void _closure(self, bool closure_plus=False) except *:
  *     fst.Closure(self._mfst.get(), fst.GetClosureType(closure_plus))             # <<<<<<<<<<<<<<
@@ -23036,11 +22137,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__closure(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 1868, __pyx_L1_error)
+    __PYX_ERR(0, 1890, __pyx_L1_error)
   }
   fst::script::Closure(__pyx_v_self->_mfst.get(), fst::script::GetClosureType(__pyx_v_closure_plus));
 
-  /* "pywrapfst.pyx":1869
+  /* "pywrapfst.pyx":1891
  *   cdef void _closure(self, bool closure_plus=False) except *:
  *     fst.Closure(self._mfst.get(), fst.GetClosureType(closure_plus))
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -23049,11 +22150,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__closure(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 1869, __pyx_L1_error)
+    __PYX_ERR(0, 1891, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1869, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1891, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1867
+  /* "pywrapfst.pyx":1889
  *     return self
  * 
  *   cdef void _closure(self, bool closure_plus=False) except *:             # <<<<<<<<<<<<<<
@@ -23069,7 +22170,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__closure(struct __pyx_obj_9pywrapfs
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":1871
+/* "pywrapfst.pyx":1893
  *     self._check_mutating_imethod()
  * 
  *   def closure(self, bool closure_plus=False):             # <<<<<<<<<<<<<<
@@ -23106,7 +22207,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_7closure(PyObject *__pyx_v_se
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "closure") < 0)) __PYX_ERR(0, 1871, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "closure") < 0)) __PYX_ERR(0, 1893, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -23117,14 +22218,14 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_7closure(PyObject *__pyx_v_se
       }
     }
     if (values[0]) {
-      __pyx_v_closure_plus = __Pyx_PyObject_IsTrue(values[0]); if (unlikely((__pyx_v_closure_plus == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1871, __pyx_L3_error)
+      __pyx_v_closure_plus = __Pyx_PyObject_IsTrue(values[0]); if (unlikely((__pyx_v_closure_plus == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1893, __pyx_L3_error)
     } else {
       __pyx_v_closure_plus = ((bool)0);
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("closure", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1871, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("closure", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1893, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.closure", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -23143,7 +22244,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_6closure(struct __pyx_obj_9py
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__closure __pyx_t_1;
   __Pyx_RefNannySetupContext("closure", 0);
 
-  /* "pywrapfst.pyx":1889
+  /* "pywrapfst.pyx":1911
  *       self.
  *     """
  *     self._closure(closure_plus)             # <<<<<<<<<<<<<<
@@ -23152,13 +22253,13 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_6closure(struct __pyx_obj_9py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_closure");
-    __PYX_ERR(0, 1889, __pyx_L1_error)
+    __PYX_ERR(0, 1911, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 1;
   __pyx_t_1.closure_plus = __pyx_v_closure_plus;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_closure(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1889, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_closure(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1911, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1890
+  /* "pywrapfst.pyx":1912
  *     """
  *     self._closure(closure_plus)
  *     return self             # <<<<<<<<<<<<<<
@@ -23170,7 +22271,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_6closure(struct __pyx_obj_9py
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1871
+  /* "pywrapfst.pyx":1893
  *     self._check_mutating_imethod()
  * 
  *   def closure(self, bool closure_plus=False):             # <<<<<<<<<<<<<<
@@ -23188,7 +22289,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_6closure(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1892
+/* "pywrapfst.pyx":1914
  *     return self
  * 
  *   cdef void _concat(self, _Fst ifst) except *:             # <<<<<<<<<<<<<<
@@ -23200,7 +22301,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__concat(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_concat", 0);
 
-  /* "pywrapfst.pyx":1893
+  /* "pywrapfst.pyx":1915
  * 
  *   cdef void _concat(self, _Fst ifst) except *:
  *     fst.Concat(self._mfst.get(), deref(ifst._fst))             # <<<<<<<<<<<<<<
@@ -23209,15 +22310,15 @@ static void __pyx_f_9pywrapfst_11_MutableFst__concat(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 1893, __pyx_L1_error)
+    __PYX_ERR(0, 1915, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 1893, __pyx_L1_error)
+    __PYX_ERR(0, 1915, __pyx_L1_error)
   }
   fst::script::Concat(__pyx_v_self->_mfst.get(), (*__pyx_v_ifst->_fst));
 
-  /* "pywrapfst.pyx":1894
+  /* "pywrapfst.pyx":1916
  *   cdef void _concat(self, _Fst ifst) except *:
  *     fst.Concat(self._mfst.get(), deref(ifst._fst))
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -23226,11 +22327,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__concat(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 1894, __pyx_L1_error)
+    __PYX_ERR(0, 1916, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1894, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1916, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1892
+  /* "pywrapfst.pyx":1914
  *     return self
  * 
  *   cdef void _concat(self, _Fst ifst) except *:             # <<<<<<<<<<<<<<
@@ -23246,7 +22347,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__concat(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":1896
+/* "pywrapfst.pyx":1918
  *     self._check_mutating_imethod()
  * 
  *   def concat(self, _Fst ifst):             # <<<<<<<<<<<<<<
@@ -23261,7 +22362,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_9concat(PyObject *__pyx_v_sel
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("concat (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 1896, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 1918, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_8concat(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_ifst));
 
   /* function exit code */
@@ -23278,7 +22379,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_8concat(struct __pyx_obj_9pyw
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("concat", 0);
 
-  /* "pywrapfst.pyx":1913
+  /* "pywrapfst.pyx":1935
  *       self.
  *     """
  *     self._concat(ifst)             # <<<<<<<<<<<<<<
@@ -23287,11 +22388,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_8concat(struct __pyx_obj_9pyw
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_concat");
-    __PYX_ERR(0, 1913, __pyx_L1_error)
+    __PYX_ERR(0, 1935, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_concat(__pyx_v_self, __pyx_v_ifst); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1913, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_concat(__pyx_v_self, __pyx_v_ifst); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1935, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1914
+  /* "pywrapfst.pyx":1936
  *     """
  *     self._concat(ifst)
  *     return self             # <<<<<<<<<<<<<<
@@ -23303,7 +22404,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_8concat(struct __pyx_obj_9pyw
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1896
+  /* "pywrapfst.pyx":1918
  *     self._check_mutating_imethod()
  * 
  *   def concat(self, _Fst ifst):             # <<<<<<<<<<<<<<
@@ -23321,7 +22422,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_8concat(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1916
+/* "pywrapfst.pyx":1938
  *     return self
  * 
  *   cdef void _connect(self) except *:             # <<<<<<<<<<<<<<
@@ -23333,7 +22434,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__connect(struct __pyx_obj_9pywrapfs
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_connect", 0);
 
-  /* "pywrapfst.pyx":1917
+  /* "pywrapfst.pyx":1939
  * 
  *   cdef void _connect(self) except *:
  *     fst.Connect(self._mfst.get())             # <<<<<<<<<<<<<<
@@ -23342,11 +22443,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__connect(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 1917, __pyx_L1_error)
+    __PYX_ERR(0, 1939, __pyx_L1_error)
   }
   fst::script::Connect(__pyx_v_self->_mfst.get());
 
-  /* "pywrapfst.pyx":1918
+  /* "pywrapfst.pyx":1940
  *   cdef void _connect(self) except *:
  *     fst.Connect(self._mfst.get())
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -23355,11 +22456,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__connect(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 1918, __pyx_L1_error)
+    __PYX_ERR(0, 1940, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1918, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1940, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1916
+  /* "pywrapfst.pyx":1938
  *     return self
  * 
  *   cdef void _connect(self) except *:             # <<<<<<<<<<<<<<
@@ -23375,7 +22476,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__connect(struct __pyx_obj_9pywrapfs
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":1920
+/* "pywrapfst.pyx":1942
  *     self._check_mutating_imethod()
  * 
  *   def connect(self):             # <<<<<<<<<<<<<<
@@ -23402,7 +22503,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_10connect(struct __pyx_obj_9p
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("connect", 0);
 
-  /* "pywrapfst.pyx":1932
+  /* "pywrapfst.pyx":1954
  *       self.
  *     """
  *     self._connect()             # <<<<<<<<<<<<<<
@@ -23411,11 +22512,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_10connect(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_connect");
-    __PYX_ERR(0, 1932, __pyx_L1_error)
+    __PYX_ERR(0, 1954, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_connect(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1932, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_connect(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1954, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1933
+  /* "pywrapfst.pyx":1955
  *     """
  *     self._connect()
  *     return self             # <<<<<<<<<<<<<<
@@ -23427,7 +22528,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_10connect(struct __pyx_obj_9p
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1920
+  /* "pywrapfst.pyx":1942
  *     self._check_mutating_imethod()
  * 
  *   def connect(self):             # <<<<<<<<<<<<<<
@@ -23445,7 +22546,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_10connect(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1935
+/* "pywrapfst.pyx":1957
  *     return self
  * 
  *   cdef void _decode(self, EncodeMapper encoder) except *:             # <<<<<<<<<<<<<<
@@ -23457,7 +22558,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__decode(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_decode", 0);
 
-  /* "pywrapfst.pyx":1936
+  /* "pywrapfst.pyx":1958
  * 
  *   cdef void _decode(self, EncodeMapper encoder) except *:
  *     fst.Decode(self._mfst.get(), deref(encoder._encoder))             # <<<<<<<<<<<<<<
@@ -23466,15 +22567,15 @@ static void __pyx_f_9pywrapfst_11_MutableFst__decode(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 1936, __pyx_L1_error)
+    __PYX_ERR(0, 1958, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_encoder) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 1936, __pyx_L1_error)
+    __PYX_ERR(0, 1958, __pyx_L1_error)
   }
   fst::script::Decode(__pyx_v_self->_mfst.get(), (*__pyx_v_encoder->_encoder));
 
-  /* "pywrapfst.pyx":1937
+  /* "pywrapfst.pyx":1959
  *   cdef void _decode(self, EncodeMapper encoder) except *:
  *     fst.Decode(self._mfst.get(), deref(encoder._encoder))
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -23483,11 +22584,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__decode(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 1937, __pyx_L1_error)
+    __PYX_ERR(0, 1959, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1937, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1959, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1935
+  /* "pywrapfst.pyx":1957
  *     return self
  * 
  *   cdef void _decode(self, EncodeMapper encoder) except *:             # <<<<<<<<<<<<<<
@@ -23503,7 +22604,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__decode(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":1939
+/* "pywrapfst.pyx":1961
  *     self._check_mutating_imethod()
  * 
  *   def decode(self, EncodeMapper encoder):             # <<<<<<<<<<<<<<
@@ -23518,7 +22619,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_13decode(PyObject *__pyx_v_se
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("decode (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_encoder), __pyx_ptype_9pywrapfst_EncodeMapper, 1, "encoder", 0))) __PYX_ERR(0, 1939, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_encoder), __pyx_ptype_9pywrapfst_EncodeMapper, 1, "encoder", 0))) __PYX_ERR(0, 1961, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_12decode(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst_EncodeMapper *)__pyx_v_encoder));
 
   /* function exit code */
@@ -23535,7 +22636,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_12decode(struct __pyx_obj_9py
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("decode", 0);
 
-  /* "pywrapfst.pyx":1955
+  /* "pywrapfst.pyx":1977
  *     See also: `encode`.
  *     """
  *     self._decode(encoder)             # <<<<<<<<<<<<<<
@@ -23544,11 +22645,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_12decode(struct __pyx_obj_9py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_decode");
-    __PYX_ERR(0, 1955, __pyx_L1_error)
+    __PYX_ERR(0, 1977, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_decode(__pyx_v_self, __pyx_v_encoder); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1955, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_decode(__pyx_v_self, __pyx_v_encoder); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1977, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1956
+  /* "pywrapfst.pyx":1978
  *     """
  *     self._decode(encoder)
  *     return self             # <<<<<<<<<<<<<<
@@ -23560,7 +22661,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_12decode(struct __pyx_obj_9py
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1939
+  /* "pywrapfst.pyx":1961
  *     self._check_mutating_imethod()
  * 
  *   def decode(self, EncodeMapper encoder):             # <<<<<<<<<<<<<<
@@ -23578,7 +22679,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_12decode(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1958
+/* "pywrapfst.pyx":1980
  *     return self
  * 
  *   cdef void _delete_arcs(self, int64 state, size_t n=0) except *:             # <<<<<<<<<<<<<<
@@ -23593,6 +22694,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_arcs(struct __pyx_obj_9pywr
   int __pyx_t_2;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("_delete_arcs", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -23600,7 +22702,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_arcs(struct __pyx_obj_9pywr
     }
   }
 
-  /* "pywrapfst.pyx":1959
+  /* "pywrapfst.pyx":1981
  * 
  *   cdef void _delete_arcs(self, int64 state, size_t n=0) except *:
  *     if not (self._mfst.get().DeleteArcs(state, n) if n else             # <<<<<<<<<<<<<<
@@ -23610,12 +22712,12 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_arcs(struct __pyx_obj_9pywr
   if ((__pyx_v_n != 0)) {
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-      __PYX_ERR(0, 1959, __pyx_L1_error)
+      __PYX_ERR(0, 1981, __pyx_L1_error)
     }
     __pyx_t_1 = __pyx_v_self->_mfst.get()->DeleteArcs(__pyx_v_state, __pyx_v_n);
   } else {
 
-    /* "pywrapfst.pyx":1960
+    /* "pywrapfst.pyx":1982
  *   cdef void _delete_arcs(self, int64 state, size_t n=0) except *:
  *     if not (self._mfst.get().DeleteArcs(state, n) if n else
  *             self._mfst.get().DeleteArcs(state)):             # <<<<<<<<<<<<<<
@@ -23624,12 +22726,12 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_arcs(struct __pyx_obj_9pywr
  */
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-      __PYX_ERR(0, 1960, __pyx_L1_error)
+      __PYX_ERR(0, 1982, __pyx_L1_error)
     }
     __pyx_t_1 = __pyx_v_self->_mfst.get()->DeleteArcs(__pyx_v_state);
   }
 
-  /* "pywrapfst.pyx":1959
+  /* "pywrapfst.pyx":1981
  * 
  *   cdef void _delete_arcs(self, int64 state, size_t n=0) except *:
  *     if not (self._mfst.get().DeleteArcs(state, n) if n else             # <<<<<<<<<<<<<<
@@ -23639,23 +22741,35 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_arcs(struct __pyx_obj_9pywr
   __pyx_t_2 = ((!(__pyx_t_1 != 0)) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":1961
+    /* "pywrapfst.pyx":1983
  *     if not (self._mfst.get().DeleteArcs(state, n) if n else
  *             self._mfst.get().DeleteArcs(state)):
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     self._check_mutating_imethod()
  * 
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1961, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple__33, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1961, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1983, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1983, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __PYX_ERR(0, 1961, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __PYX_ERR(0, 1983, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":1959
+    /* "pywrapfst.pyx":1981
  * 
  *   cdef void _delete_arcs(self, int64 state, size_t n=0) except *:
  *     if not (self._mfst.get().DeleteArcs(state, n) if n else             # <<<<<<<<<<<<<<
@@ -23664,7 +22778,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_arcs(struct __pyx_obj_9pywr
  */
   }
 
-  /* "pywrapfst.pyx":1962
+  /* "pywrapfst.pyx":1984
  *             self._mfst.get().DeleteArcs(state)):
  *       raise FstIndexError("State index out of range")
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -23673,11 +22787,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_arcs(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 1962, __pyx_L1_error)
+    __PYX_ERR(0, 1984, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1962, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1984, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1958
+  /* "pywrapfst.pyx":1980
  *     return self
  * 
  *   cdef void _delete_arcs(self, int64 state, size_t n=0) except *:             # <<<<<<<<<<<<<<
@@ -23690,12 +22804,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_arcs(struct __pyx_obj_9pywr
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst._MutableFst._delete_arcs", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":1964
+/* "pywrapfst.pyx":1986
  *     self._check_mutating_imethod()
  * 
  *   def delete_arcs(self, int64 state, size_t n=0):             # <<<<<<<<<<<<<<
@@ -23739,7 +22854,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_15delete_arcs(PyObject *__pyx
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "delete_arcs") < 0)) __PYX_ERR(0, 1964, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "delete_arcs") < 0)) __PYX_ERR(0, 1986, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -23750,16 +22865,16 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_15delete_arcs(PyObject *__pyx
         default: goto __pyx_L5_argtuple_error;
       }
     }
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1964, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 1986, __pyx_L3_error)
     if (values[1]) {
-      __pyx_v_n = __Pyx_PyInt_As_size_t(values[1]); if (unlikely((__pyx_v_n == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1964, __pyx_L3_error)
+      __pyx_v_n = __Pyx_PyInt_As_size_t(values[1]); if (unlikely((__pyx_v_n == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 1986, __pyx_L3_error)
     } else {
       __pyx_v_n = ((size_t)0);
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("delete_arcs", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1964, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("delete_arcs", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1986, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.delete_arcs", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -23778,7 +22893,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_14delete_arcs(struct __pyx_ob
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__delete_arcs __pyx_t_1;
   __Pyx_RefNannySetupContext("delete_arcs", 0);
 
-  /* "pywrapfst.pyx":1984
+  /* "pywrapfst.pyx":2006
  *     See also: `delete_states`.
  *     """
  *     self._delete_arcs(state, n)             # <<<<<<<<<<<<<<
@@ -23787,13 +22902,13 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_14delete_arcs(struct __pyx_ob
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_delete_arcs");
-    __PYX_ERR(0, 1984, __pyx_L1_error)
+    __PYX_ERR(0, 2006, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 1;
   __pyx_t_1.n = __pyx_v_n;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_delete_arcs(__pyx_v_self, __pyx_v_state, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1984, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_delete_arcs(__pyx_v_self, __pyx_v_state, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2006, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1985
+  /* "pywrapfst.pyx":2007
  *     """
  *     self._delete_arcs(state, n)
  *     return self             # <<<<<<<<<<<<<<
@@ -23805,7 +22920,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_14delete_arcs(struct __pyx_ob
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1964
+  /* "pywrapfst.pyx":1986
  *     self._check_mutating_imethod()
  * 
  *   def delete_arcs(self, int64 state, size_t n=0):             # <<<<<<<<<<<<<<
@@ -23823,7 +22938,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_14delete_arcs(struct __pyx_ob
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":1987
+/* "pywrapfst.pyx":2009
  *     return self
  * 
  *   cdef void _delete_states(self, states=None) except *:             # <<<<<<<<<<<<<<
@@ -23838,6 +22953,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_states(struct __pyx_obj_9py
   std::vector<__pyx_t_10basictypes_int64>  __pyx_t_2;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("_delete_states", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -23845,17 +22961,17 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_states(struct __pyx_obj_9py
     }
   }
 
-  /* "pywrapfst.pyx":1989
+  /* "pywrapfst.pyx":2011
  *   cdef void _delete_states(self, states=None) except *:
  *     # Only the former signature has a possible indexing failure.
  *     if states:             # <<<<<<<<<<<<<<
  *       if not self._mfst.get().DeleteStates(<const vector[int64]> states):
  *         raise FstIndexError("State index out of range")
  */
-  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_states); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 1989, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_states); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 2011, __pyx_L1_error)
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":1990
+    /* "pywrapfst.pyx":2012
  *     # Only the former signature has a possible indexing failure.
  *     if states:
  *       if not self._mfst.get().DeleteStates(<const vector[int64]> states):             # <<<<<<<<<<<<<<
@@ -23864,29 +22980,41 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_states(struct __pyx_obj_9py
  */
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-      __PYX_ERR(0, 1990, __pyx_L1_error)
+      __PYX_ERR(0, 2012, __pyx_L1_error)
     }
-    __pyx_t_2 = __pyx_convert_vector_from_py___pyx_t_10basictypes_int64(__pyx_v_states); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1990, __pyx_L1_error)
+    __pyx_t_2 = __pyx_convert_vector_from_py___pyx_t_10basictypes_int64(__pyx_v_states); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2012, __pyx_L1_error)
     __pyx_t_1 = ((!(__pyx_v_self->_mfst.get()->DeleteStates(((std::vector<__pyx_t_10basictypes_int64>  const )__pyx_t_2)) != 0)) != 0);
     if (unlikely(__pyx_t_1)) {
 
-      /* "pywrapfst.pyx":1991
+      /* "pywrapfst.pyx":2013
  *     if states:
  *       if not self._mfst.get().DeleteStates(<const vector[int64]> states):
  *         raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     else:
  *       self._mfst.get().DeleteStates()
  */
-      __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1991, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple__34, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1991, __pyx_L1_error)
+      __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2013, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+      __pyx_t_5 = NULL;
+      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+        if (likely(__pyx_t_5)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+          __Pyx_INCREF(__pyx_t_5);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_4, function);
+        }
+      }
+      __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_u_State_index_out_of_range);
+      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2013, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __PYX_ERR(0, 1991, __pyx_L1_error)
+      __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __PYX_ERR(0, 2013, __pyx_L1_error)
 
-      /* "pywrapfst.pyx":1990
+      /* "pywrapfst.pyx":2012
  *     # Only the former signature has a possible indexing failure.
  *     if states:
  *       if not self._mfst.get().DeleteStates(<const vector[int64]> states):             # <<<<<<<<<<<<<<
@@ -23895,7 +23023,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_states(struct __pyx_obj_9py
  */
     }
 
-    /* "pywrapfst.pyx":1989
+    /* "pywrapfst.pyx":2011
  *   cdef void _delete_states(self, states=None) except *:
  *     # Only the former signature has a possible indexing failure.
  *     if states:             # <<<<<<<<<<<<<<
@@ -23905,7 +23033,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_states(struct __pyx_obj_9py
     goto __pyx_L3;
   }
 
-  /* "pywrapfst.pyx":1993
+  /* "pywrapfst.pyx":2015
  *         raise FstIndexError("State index out of range")
  *     else:
  *       self._mfst.get().DeleteStates()             # <<<<<<<<<<<<<<
@@ -23915,13 +23043,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_states(struct __pyx_obj_9py
   /*else*/ {
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-      __PYX_ERR(0, 1993, __pyx_L1_error)
+      __PYX_ERR(0, 2015, __pyx_L1_error)
     }
     __pyx_v_self->_mfst.get()->DeleteStates();
   }
   __pyx_L3:;
 
-  /* "pywrapfst.pyx":1994
+  /* "pywrapfst.pyx":2016
  *     else:
  *       self._mfst.get().DeleteStates()
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -23930,11 +23058,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_states(struct __pyx_obj_9py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 1994, __pyx_L1_error)
+    __PYX_ERR(0, 2016, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1994, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2016, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":1987
+  /* "pywrapfst.pyx":2009
  *     return self
  * 
  *   cdef void _delete_states(self, states=None) except *:             # <<<<<<<<<<<<<<
@@ -23947,12 +23075,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__delete_states(struct __pyx_obj_9py
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst._MutableFst._delete_states", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":1996
+/* "pywrapfst.pyx":2018
  *     self._check_mutating_imethod()
  * 
  *   def delete_states(self, states=None):             # <<<<<<<<<<<<<<
@@ -23990,7 +23119,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_17delete_states(PyObject *__p
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "delete_states") < 0)) __PYX_ERR(0, 1996, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "delete_states") < 0)) __PYX_ERR(0, 2018, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -24004,7 +23133,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_17delete_states(PyObject *__p
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("delete_states", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 1996, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("delete_states", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2018, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.delete_states", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -24023,7 +23152,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_16delete_states(struct __pyx_
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__delete_states __pyx_t_1;
   __Pyx_RefNannySetupContext("delete_states", 0);
 
-  /* "pywrapfst.pyx":2014
+  /* "pywrapfst.pyx":2036
  *     See also: `delete_arcs`.
  *     """
  *     self._delete_states(states)             # <<<<<<<<<<<<<<
@@ -24032,13 +23161,13 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_16delete_states(struct __pyx_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_delete_states");
-    __PYX_ERR(0, 2014, __pyx_L1_error)
+    __PYX_ERR(0, 2036, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 1;
   __pyx_t_1.states = __pyx_v_states;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_delete_states(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2014, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_delete_states(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2036, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2015
+  /* "pywrapfst.pyx":2037
  *     """
  *     self._delete_states(states)
  *     return self             # <<<<<<<<<<<<<<
@@ -24050,7 +23179,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_16delete_states(struct __pyx_
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":1996
+  /* "pywrapfst.pyx":2018
  *     self._check_mutating_imethod()
  * 
  *   def delete_states(self, states=None):             # <<<<<<<<<<<<<<
@@ -24068,7 +23197,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_16delete_states(struct __pyx_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2017
+/* "pywrapfst.pyx":2039
  *     return self
  * 
  *   cdef void _encode(self, EncodeMapper encoder) except *:             # <<<<<<<<<<<<<<
@@ -24080,7 +23209,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__encode(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_encode", 0);
 
-  /* "pywrapfst.pyx":2018
+  /* "pywrapfst.pyx":2040
  * 
  *   cdef void _encode(self, EncodeMapper encoder) except *:
  *     fst.Encode(self._mfst.get(), encoder._encoder.get())             # <<<<<<<<<<<<<<
@@ -24089,15 +23218,15 @@ static void __pyx_f_9pywrapfst_11_MutableFst__encode(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2018, __pyx_L1_error)
+    __PYX_ERR(0, 2040, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_encoder) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encoder");
-    __PYX_ERR(0, 2018, __pyx_L1_error)
+    __PYX_ERR(0, 2040, __pyx_L1_error)
   }
   fst::script::Encode(__pyx_v_self->_mfst.get(), __pyx_v_encoder->_encoder.get());
 
-  /* "pywrapfst.pyx":2019
+  /* "pywrapfst.pyx":2041
  *   cdef void _encode(self, EncodeMapper encoder) except *:
  *     fst.Encode(self._mfst.get(), encoder._encoder.get())
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -24106,11 +23235,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__encode(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2019, __pyx_L1_error)
+    __PYX_ERR(0, 2041, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2019, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2041, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2017
+  /* "pywrapfst.pyx":2039
  *     return self
  * 
  *   cdef void _encode(self, EncodeMapper encoder) except *:             # <<<<<<<<<<<<<<
@@ -24126,7 +23255,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__encode(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2021
+/* "pywrapfst.pyx":2043
  *     self._check_mutating_imethod()
  * 
  *   def encode(self, EncodeMapper encoder):             # <<<<<<<<<<<<<<
@@ -24141,7 +23270,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_19encode(PyObject *__pyx_v_se
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("encode (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_encoder), __pyx_ptype_9pywrapfst_EncodeMapper, 1, "encoder", 0))) __PYX_ERR(0, 2021, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_encoder), __pyx_ptype_9pywrapfst_EncodeMapper, 1, "encoder", 0))) __PYX_ERR(0, 2043, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_18encode(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst_EncodeMapper *)__pyx_v_encoder));
 
   /* function exit code */
@@ -24158,7 +23287,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_18encode(struct __pyx_obj_9py
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("encode", 0);
 
-  /* "pywrapfst.pyx":2042
+  /* "pywrapfst.pyx":2064
  *     See also: `decode`.
  *     """
  *     self._encode(encoder)             # <<<<<<<<<<<<<<
@@ -24167,11 +23296,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_18encode(struct __pyx_obj_9py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_encode");
-    __PYX_ERR(0, 2042, __pyx_L1_error)
+    __PYX_ERR(0, 2064, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_encode(__pyx_v_self, __pyx_v_encoder); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2042, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_encode(__pyx_v_self, __pyx_v_encoder); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2064, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2043
+  /* "pywrapfst.pyx":2065
  *     """
  *     self._encode(encoder)
  *     return self             # <<<<<<<<<<<<<<
@@ -24183,7 +23312,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_18encode(struct __pyx_obj_9py
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2021
+  /* "pywrapfst.pyx":2043
  *     self._check_mutating_imethod()
  * 
  *   def encode(self, EncodeMapper encoder):             # <<<<<<<<<<<<<<
@@ -24201,7 +23330,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_18encode(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2045
+/* "pywrapfst.pyx":2067
  *     return self
  * 
  *   cdef void _invert(self) except *:             # <<<<<<<<<<<<<<
@@ -24213,7 +23342,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__invert(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_invert", 0);
 
-  /* "pywrapfst.pyx":2046
+  /* "pywrapfst.pyx":2068
  * 
  *   cdef void _invert(self) except *:
  *     fst.Invert(self._mfst.get())             # <<<<<<<<<<<<<<
@@ -24222,11 +23351,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__invert(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2046, __pyx_L1_error)
+    __PYX_ERR(0, 2068, __pyx_L1_error)
   }
   fst::script::Invert(__pyx_v_self->_mfst.get());
 
-  /* "pywrapfst.pyx":2047
+  /* "pywrapfst.pyx":2069
  *   cdef void _invert(self) except *:
  *     fst.Invert(self._mfst.get())
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -24235,11 +23364,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__invert(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2047, __pyx_L1_error)
+    __PYX_ERR(0, 2069, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2047, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2069, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2045
+  /* "pywrapfst.pyx":2067
  *     return self
  * 
  *   cdef void _invert(self) except *:             # <<<<<<<<<<<<<<
@@ -24255,7 +23384,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__invert(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2049
+/* "pywrapfst.pyx":2071
  *     self._check_mutating_imethod()
  * 
  *   def invert(self):             # <<<<<<<<<<<<<<
@@ -24282,7 +23411,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_20invert(struct __pyx_obj_9py
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("invert", 0);
 
-  /* "pywrapfst.pyx":2061
+  /* "pywrapfst.pyx":2083
  *       self.
  *     """
  *     self._invert()             # <<<<<<<<<<<<<<
@@ -24291,11 +23420,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_20invert(struct __pyx_obj_9py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_invert");
-    __PYX_ERR(0, 2061, __pyx_L1_error)
+    __PYX_ERR(0, 2083, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_invert(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2061, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_invert(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2083, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2062
+  /* "pywrapfst.pyx":2084
  *     """
  *     self._invert()
  *     return self             # <<<<<<<<<<<<<<
@@ -24307,7 +23436,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_20invert(struct __pyx_obj_9py
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2049
+  /* "pywrapfst.pyx":2071
  *     self._check_mutating_imethod()
  * 
  *   def invert(self):             # <<<<<<<<<<<<<<
@@ -24325,7 +23454,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_20invert(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2064
+/* "pywrapfst.pyx":2086
  *     return self
  * 
  *   cdef void _minimize(self, float delta=fst.kShortestDelta,             # <<<<<<<<<<<<<<
@@ -24334,9 +23463,9 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_20invert(struct __pyx_obj_9py
  */
 
 static void __pyx_f_9pywrapfst_11_MutableFst__minimize(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self, struct __pyx_opt_args_9pywrapfst_11_MutableFst__minimize *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__35;
+  float __pyx_v_delta = __pyx_k__11;
 
-  /* "pywrapfst.pyx":2065
+  /* "pywrapfst.pyx":2087
  * 
  *   cdef void _minimize(self, float delta=fst.kShortestDelta,
  *                       bool allow_nondet=False) except *:             # <<<<<<<<<<<<<<
@@ -24355,7 +23484,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__minimize(struct __pyx_obj_9pywrapf
     }
   }
 
-  /* "pywrapfst.pyx":2067
+  /* "pywrapfst.pyx":2089
  *                       bool allow_nondet=False) except *:
  *     # This runs in-place when the second argument is null.
  *     fst.Minimize(self._mfst.get(), NULL, delta, allow_nondet)             # <<<<<<<<<<<<<<
@@ -24364,11 +23493,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__minimize(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2067, __pyx_L1_error)
+    __PYX_ERR(0, 2089, __pyx_L1_error)
   }
   fst::script::Minimize(__pyx_v_self->_mfst.get(), NULL, __pyx_v_delta, __pyx_v_allow_nondet);
 
-  /* "pywrapfst.pyx":2068
+  /* "pywrapfst.pyx":2090
  *     # This runs in-place when the second argument is null.
  *     fst.Minimize(self._mfst.get(), NULL, delta, allow_nondet)
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -24377,11 +23506,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__minimize(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2068, __pyx_L1_error)
+    __PYX_ERR(0, 2090, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2068, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2090, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2064
+  /* "pywrapfst.pyx":2086
  *     return self
  * 
  *   cdef void _minimize(self, float delta=fst.kShortestDelta,             # <<<<<<<<<<<<<<
@@ -24397,7 +23526,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__minimize(struct __pyx_obj_9pywrapf
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2070
+/* "pywrapfst.pyx":2092
  *     self._check_mutating_imethod()
  * 
  *   def minimize(self, float delta=fst.kShortestDelta, bool allow_nondet=False):             # <<<<<<<<<<<<<<
@@ -24443,7 +23572,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_23minimize(PyObject *__pyx_v_
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "minimize") < 0)) __PYX_ERR(0, 2070, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "minimize") < 0)) __PYX_ERR(0, 2092, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -24456,19 +23585,19 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_23minimize(PyObject *__pyx_v_
       }
     }
     if (values[0]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 2070, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 2092, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__36;
+      __pyx_v_delta = __pyx_k__12;
     }
     if (values[1]) {
-      __pyx_v_allow_nondet = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_allow_nondet == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2070, __pyx_L3_error)
+      __pyx_v_allow_nondet = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_allow_nondet == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2092, __pyx_L3_error)
     } else {
       __pyx_v_allow_nondet = ((bool)0);
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("minimize", 0, 0, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2070, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("minimize", 0, 0, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2092, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.minimize", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -24487,7 +23616,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_22minimize(struct __pyx_obj_9
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__minimize __pyx_t_1;
   __Pyx_RefNannySetupContext("minimize", 0);
 
-  /* "pywrapfst.pyx":2096
+  /* "pywrapfst.pyx":2118
  *       self.
  *     """
  *     self._minimize(delta, allow_nondet)             # <<<<<<<<<<<<<<
@@ -24496,14 +23625,14 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_22minimize(struct __pyx_obj_9
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_minimize");
-    __PYX_ERR(0, 2096, __pyx_L1_error)
+    __PYX_ERR(0, 2118, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 2;
   __pyx_t_1.delta = __pyx_v_delta;
   __pyx_t_1.allow_nondet = __pyx_v_allow_nondet;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_minimize(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2096, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_minimize(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2118, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2097
+  /* "pywrapfst.pyx":2119
  *     """
  *     self._minimize(delta, allow_nondet)
  *     return self             # <<<<<<<<<<<<<<
@@ -24515,7 +23644,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_22minimize(struct __pyx_obj_9
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2070
+  /* "pywrapfst.pyx":2092
  *     self._check_mutating_imethod()
  * 
  *   def minimize(self, float delta=fst.kShortestDelta, bool allow_nondet=False):             # <<<<<<<<<<<<<<
@@ -24533,7 +23662,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_22minimize(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2099
+/* "pywrapfst.pyx":2121
  *     return self
  * 
  *   cpdef MutableArcIterator mutable_arcs(self, int64 state):             # <<<<<<<<<<<<<<
@@ -24550,75 +23679,60 @@ static struct __pyx_obj_9pywrapfst_MutableArcIterator *__pyx_f_9pywrapfst_11_Mut
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
   __Pyx_RefNannySetupContext("mutable_arcs", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_mutable_arcs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2099, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_25mutable_arcs)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2099, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_mutable_arcs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2121, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11_MutableFst_25mutable_arcs)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2121, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2099, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2121, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2099, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2099, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2099, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2099, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_MutableArcIterator))))) __PYX_ERR(0, 2121, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst_MutableArcIterator *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_MutableArcIterator))))) __PYX_ERR(0, 2099, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst_MutableArcIterator *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":2113
+  /* "pywrapfst.pyx":2135
  *     See also: `arcs`, `states`.
  *     """
  *     return MutableArcIterator(self, state)             # <<<<<<<<<<<<<<
@@ -24626,9 +23740,9 @@ static struct __pyx_obj_9pywrapfst_MutableArcIterator *__pyx_f_9pywrapfst_11_Mut
  *   def mutable_input_symbols(self):
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2113, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_v_state); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2135, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2113, __pyx_L1_error)
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2135, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_INCREF(((PyObject *)__pyx_v_self));
   __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
@@ -24636,14 +23750,14 @@ static struct __pyx_obj_9pywrapfst_MutableArcIterator *__pyx_f_9pywrapfst_11_Mut
   __Pyx_GIVEREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_MutableArcIterator), __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2113, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_MutableArcIterator), __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2135, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_r = ((struct __pyx_obj_9pywrapfst_MutableArcIterator *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2099
+  /* "pywrapfst.pyx":2121
  *     return self
  * 
  *   cpdef MutableArcIterator mutable_arcs(self, int64 state):             # <<<<<<<<<<<<<<
@@ -24658,7 +23772,6 @@ static struct __pyx_obj_9pywrapfst_MutableArcIterator *__pyx_f_9pywrapfst_11_Mut
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_AddTraceback("pywrapfst._MutableFst.mutable_arcs", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -24676,7 +23789,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_25mutable_arcs(PyObject *__py
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("mutable_arcs (wrapper)", 0);
   assert(__pyx_arg_state); {
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2099, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2121, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -24697,7 +23810,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_24mutable_arcs(struct __pyx_o
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("mutable_arcs", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_11_MutableFst_mutable_arcs(__pyx_v_self, __pyx_v_state, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2099, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_11_MutableFst_mutable_arcs(__pyx_v_self, __pyx_v_state, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2121, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -24714,7 +23827,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_24mutable_arcs(struct __pyx_o
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2115
+/* "pywrapfst.pyx":2137
  *     return MutableArcIterator(self, state)
  * 
  *   def mutable_input_symbols(self):             # <<<<<<<<<<<<<<
@@ -24737,75 +23850,75 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_27mutable_input_symbols(PyObj
 }
 
 static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_26mutable_input_symbols(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self) {
-  fst::SymbolTable *__pyx_v_tst;
+  fst::SymbolTable *__pyx_v_syms;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("mutable_input_symbols", 0);
 
-  /* "pywrapfst.pyx":2121
+  /* "pywrapfst.pyx":2143
  *     Returns the FST's (mutable) input symbol table, or None if none is present.
  *     """
- *     cdef fst.SymbolTable *tst = self._mfst.get().MutableInputSymbols()             # <<<<<<<<<<<<<<
- *     if tst == NULL:
+ *     cdef fst.SymbolTable *syms = self._mfst.get().MutableInputSymbols()             # <<<<<<<<<<<<<<
+ *     if syms == NULL:
  *       return
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2121, __pyx_L1_error)
+    __PYX_ERR(0, 2143, __pyx_L1_error)
   }
-  __pyx_v_tst = __pyx_v_self->_mfst.get()->MutableInputSymbols();
+  __pyx_v_syms = __pyx_v_self->_mfst.get()->MutableInputSymbols();
 
-  /* "pywrapfst.pyx":2122
+  /* "pywrapfst.pyx":2144
  *     """
- *     cdef fst.SymbolTable *tst = self._mfst.get().MutableInputSymbols()
- *     if tst == NULL:             # <<<<<<<<<<<<<<
+ *     cdef fst.SymbolTable *syms = self._mfst.get().MutableInputSymbols()
+ *     if syms == NULL:             # <<<<<<<<<<<<<<
  *       return
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  */
-  __pyx_t_1 = ((__pyx_v_tst == NULL) != 0);
+  __pyx_t_1 = ((__pyx_v_syms == NULL) != 0);
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":2123
- *     cdef fst.SymbolTable *tst = self._mfst.get().MutableInputSymbols()
- *     if tst == NULL:
+    /* "pywrapfst.pyx":2145
+ *     cdef fst.SymbolTable *syms = self._mfst.get().MutableInputSymbols()
+ *     if syms == NULL:
  *       return             # <<<<<<<<<<<<<<
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  * 
  */
     __Pyx_XDECREF(__pyx_r);
     __pyx_r = Py_None; __Pyx_INCREF(Py_None);
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":2122
+    /* "pywrapfst.pyx":2144
  *     """
- *     cdef fst.SymbolTable *tst = self._mfst.get().MutableInputSymbols()
- *     if tst == NULL:             # <<<<<<<<<<<<<<
+ *     cdef fst.SymbolTable *syms = self._mfst.get().MutableInputSymbols()
+ *     if syms == NULL:             # <<<<<<<<<<<<<<
  *       return
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  */
   }
 
-  /* "pywrapfst.pyx":2124
- *     if tst == NULL:
+  /* "pywrapfst.pyx":2146
+ *     if syms == NULL:
  *       return
- *     return _init_MutableFstSymbolTable(tst, self._mfst)             # <<<<<<<<<<<<<<
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)             # <<<<<<<<<<<<<<
  * 
  *   def mutable_output_symbols(self):
  */
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2124, __pyx_L1_error)
+    __PYX_ERR(0, 2146, __pyx_L1_error)
   }
-  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFstSymbolTable(__pyx_v_tst, __pyx_v_self->_mfst)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2124, __pyx_L1_error)
+  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFstSymbolTable(__pyx_v_syms, __pyx_v_self->_mfst)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2146, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2115
+  /* "pywrapfst.pyx":2137
  *     return MutableArcIterator(self, state)
  * 
  *   def mutable_input_symbols(self):             # <<<<<<<<<<<<<<
@@ -24824,8 +23937,8 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_26mutable_input_symbols(struc
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2126
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+/* "pywrapfst.pyx":2148
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  * 
  *   def mutable_output_symbols(self):             # <<<<<<<<<<<<<<
  *     """
@@ -24847,76 +23960,76 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_29mutable_output_symbols(PyOb
 }
 
 static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_28mutable_output_symbols(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self) {
-  fst::SymbolTable *__pyx_v_tst;
+  fst::SymbolTable *__pyx_v_syms;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("mutable_output_symbols", 0);
 
-  /* "pywrapfst.pyx":2132
+  /* "pywrapfst.pyx":2154
  *     Returns the FST's (mutable) output symbol table, or None if none is present.
  *     """
- *     cdef fst.SymbolTable *tst = self._mfst.get().MutableOutputSymbols()             # <<<<<<<<<<<<<<
- *     if tst == NULL:
+ *     cdef fst.SymbolTable *syms = self._mfst.get().MutableOutputSymbols()             # <<<<<<<<<<<<<<
+ *     if syms == NULL:
  *       return
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2132, __pyx_L1_error)
+    __PYX_ERR(0, 2154, __pyx_L1_error)
   }
-  __pyx_v_tst = __pyx_v_self->_mfst.get()->MutableOutputSymbols();
+  __pyx_v_syms = __pyx_v_self->_mfst.get()->MutableOutputSymbols();
 
-  /* "pywrapfst.pyx":2133
+  /* "pywrapfst.pyx":2155
  *     """
- *     cdef fst.SymbolTable *tst = self._mfst.get().MutableOutputSymbols()
- *     if tst == NULL:             # <<<<<<<<<<<<<<
+ *     cdef fst.SymbolTable *syms = self._mfst.get().MutableOutputSymbols()
+ *     if syms == NULL:             # <<<<<<<<<<<<<<
  *       return
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  */
-  __pyx_t_1 = ((__pyx_v_tst == NULL) != 0);
+  __pyx_t_1 = ((__pyx_v_syms == NULL) != 0);
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":2134
- *     cdef fst.SymbolTable *tst = self._mfst.get().MutableOutputSymbols()
- *     if tst == NULL:
+    /* "pywrapfst.pyx":2156
+ *     cdef fst.SymbolTable *syms = self._mfst.get().MutableOutputSymbols()
+ *     if syms == NULL:
  *       return             # <<<<<<<<<<<<<<
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  * 
  */
     __Pyx_XDECREF(__pyx_r);
     __pyx_r = Py_None; __Pyx_INCREF(Py_None);
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":2133
+    /* "pywrapfst.pyx":2155
  *     """
- *     cdef fst.SymbolTable *tst = self._mfst.get().MutableOutputSymbols()
- *     if tst == NULL:             # <<<<<<<<<<<<<<
+ *     cdef fst.SymbolTable *syms = self._mfst.get().MutableOutputSymbols()
+ *     if syms == NULL:             # <<<<<<<<<<<<<<
  *       return
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  */
   }
 
-  /* "pywrapfst.pyx":2135
- *     if tst == NULL:
+  /* "pywrapfst.pyx":2157
+ *     if syms == NULL:
  *       return
- *     return _init_MutableFstSymbolTable(tst, self._mfst)             # <<<<<<<<<<<<<<
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)             # <<<<<<<<<<<<<<
  * 
  *   cpdef int64 num_states(self):
  */
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2135, __pyx_L1_error)
+    __PYX_ERR(0, 2157, __pyx_L1_error)
   }
-  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFstSymbolTable(__pyx_v_tst, __pyx_v_self->_mfst)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2135, __pyx_L1_error)
+  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFstSymbolTable(__pyx_v_syms, __pyx_v_self->_mfst)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2157, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2126
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+  /* "pywrapfst.pyx":2148
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  * 
  *   def mutable_output_symbols(self):             # <<<<<<<<<<<<<<
  *     """
@@ -24934,8 +24047,8 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_28mutable_output_symbols(stru
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2137
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+/* "pywrapfst.pyx":2159
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  * 
  *   cpdef int64 num_states(self):             # <<<<<<<<<<<<<<
  *     """
@@ -24955,39 +24068,52 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_11_MutableFst_num_states(st
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_states); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2137, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_31num_states)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_num_states); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2159, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11_MutableFst_31num_states)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2159, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2159, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2137, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2137, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2137, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":2143
+  /* "pywrapfst.pyx":2165
  *     Returns the number of states.
  *     """
  *     return self._mfst.get().NumStates()             # <<<<<<<<<<<<<<
@@ -24996,13 +24122,13 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_11_MutableFst_num_states(st
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2143, __pyx_L1_error)
+    __PYX_ERR(0, 2165, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_mfst.get()->NumStates();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2137
- *     return _init_MutableFstSymbolTable(tst, self._mfst)
+  /* "pywrapfst.pyx":2159
+ *     return _init_MutableFstSymbolTable(syms, self._mfst)
  * 
  *   cpdef int64 num_states(self):             # <<<<<<<<<<<<<<
  *     """
@@ -25042,7 +24168,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_30num_states(struct __pyx_obj
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("num_states", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_11_MutableFst_num_states(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2137, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_11_MutableFst_num_states(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2159, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -25059,7 +24185,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_30num_states(struct __pyx_obj
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2145
+/* "pywrapfst.pyx":2167
  *     return self._mfst.get().NumStates()
  * 
  *   cdef void _project(self, bool project_output=False) except *:             # <<<<<<<<<<<<<<
@@ -25077,7 +24203,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__project(struct __pyx_obj_9pywrapfs
     }
   }
 
-  /* "pywrapfst.pyx":2146
+  /* "pywrapfst.pyx":2168
  * 
  *   cdef void _project(self, bool project_output=False) except *:
  *     fst.Project(self._mfst.get(), fst.GetProjectType(project_output))             # <<<<<<<<<<<<<<
@@ -25086,11 +24212,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__project(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2146, __pyx_L1_error)
+    __PYX_ERR(0, 2168, __pyx_L1_error)
   }
   fst::script::Project(__pyx_v_self->_mfst.get(), fst::script::GetProjectType(__pyx_v_project_output));
 
-  /* "pywrapfst.pyx":2147
+  /* "pywrapfst.pyx":2169
  *   cdef void _project(self, bool project_output=False) except *:
  *     fst.Project(self._mfst.get(), fst.GetProjectType(project_output))
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -25099,11 +24225,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__project(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2147, __pyx_L1_error)
+    __PYX_ERR(0, 2169, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2147, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2169, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2145
+  /* "pywrapfst.pyx":2167
  *     return self._mfst.get().NumStates()
  * 
  *   cdef void _project(self, bool project_output=False) except *:             # <<<<<<<<<<<<<<
@@ -25119,7 +24245,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__project(struct __pyx_obj_9pywrapfs
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2149
+/* "pywrapfst.pyx":2171
  *     self._check_mutating_imethod()
  * 
  *   def project(self, bool project_output=False):             # <<<<<<<<<<<<<<
@@ -25156,7 +24282,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_33project(PyObject *__pyx_v_s
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "project") < 0)) __PYX_ERR(0, 2149, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "project") < 0)) __PYX_ERR(0, 2171, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -25167,14 +24293,14 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_33project(PyObject *__pyx_v_s
       }
     }
     if (values[0]) {
-      __pyx_v_project_output = __Pyx_PyObject_IsTrue(values[0]); if (unlikely((__pyx_v_project_output == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2149, __pyx_L3_error)
+      __pyx_v_project_output = __Pyx_PyObject_IsTrue(values[0]); if (unlikely((__pyx_v_project_output == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2171, __pyx_L3_error)
     } else {
       __pyx_v_project_output = ((bool)0);
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("project", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2149, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("project", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2171, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.project", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -25193,7 +24319,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_32project(struct __pyx_obj_9p
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__project __pyx_t_1;
   __Pyx_RefNannySetupContext("project", 0);
 
-  /* "pywrapfst.pyx":2167
+  /* "pywrapfst.pyx":2189
  *     See also: `decode`, `encode`, `relabel_pairs`, `relabel_symbols`.
  *     """
  *     self._project(project_output)             # <<<<<<<<<<<<<<
@@ -25202,13 +24328,13 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_32project(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_project");
-    __PYX_ERR(0, 2167, __pyx_L1_error)
+    __PYX_ERR(0, 2189, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 1;
   __pyx_t_1.project_output = __pyx_v_project_output;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_project(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2167, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_project(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2189, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2168
+  /* "pywrapfst.pyx":2190
  *     """
  *     self._project(project_output)
  *     return self             # <<<<<<<<<<<<<<
@@ -25220,7 +24346,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_32project(struct __pyx_obj_9p
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2149
+  /* "pywrapfst.pyx":2171
  *     self._check_mutating_imethod()
  * 
  *   def project(self, bool project_output=False):             # <<<<<<<<<<<<<<
@@ -25238,7 +24364,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_32project(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2170
+/* "pywrapfst.pyx":2192
  *     return self
  * 
  *   cdef void _prune(self, float delta=fst.kDelta, int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
@@ -25247,10 +24373,10 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_32project(struct __pyx_obj_9p
  */
 
 static void __pyx_f_9pywrapfst_11_MutableFst__prune(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self, struct __pyx_opt_args_9pywrapfst_11_MutableFst__prune *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__37;
-  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__38;
+  float __pyx_v_delta = __pyx_k__13;
+  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__14;
 
-  /* "pywrapfst.pyx":2171
+  /* "pywrapfst.pyx":2193
  * 
  *   cdef void _prune(self, float delta=fst.kDelta, int64 nstate=fst.kNoStateId,
  *                    weight=None) except *:             # <<<<<<<<<<<<<<
@@ -25274,7 +24400,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__prune(struct __pyx_obj_9pywrapfst_
     }
   }
 
-  /* "pywrapfst.pyx":2173
+  /* "pywrapfst.pyx":2195
  *                    weight=None) except *:
  *     # Threshold is set to semiring Zero (no pruning) if no weight is specified.
  *     cdef fst.WeightClass wc = _get_WeightClass_or_Zero(self.weight_type(),             # <<<<<<<<<<<<<<
@@ -25283,20 +24409,20 @@ static void __pyx_f_9pywrapfst_11_MutableFst__prune(struct __pyx_obj_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-    __PYX_ERR(0, 2173, __pyx_L1_error)
+    __PYX_ERR(0, 2195, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":2174
+  /* "pywrapfst.pyx":2196
  *     # Threshold is set to semiring Zero (no pruning) if no weight is specified.
  *     cdef fst.WeightClass wc = _get_WeightClass_or_Zero(self.weight_type(),
  *                                                        weight)             # <<<<<<<<<<<<<<
  *     fst.Prune(self._mfst.get(), wc, nstate, delta)
  *     self._check_mutating_imethod()
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.weight_type(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2173, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.weight_type(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2195, __pyx_L1_error)
   __pyx_v_wc = __pyx_t_1;
 
-  /* "pywrapfst.pyx":2175
+  /* "pywrapfst.pyx":2197
  *     cdef fst.WeightClass wc = _get_WeightClass_or_Zero(self.weight_type(),
  *                                                        weight)
  *     fst.Prune(self._mfst.get(), wc, nstate, delta)             # <<<<<<<<<<<<<<
@@ -25305,11 +24431,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__prune(struct __pyx_obj_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2175, __pyx_L1_error)
+    __PYX_ERR(0, 2197, __pyx_L1_error)
   }
   fst::script::Prune(__pyx_v_self->_mfst.get(), __pyx_v_wc, __pyx_v_nstate, __pyx_v_delta);
 
-  /* "pywrapfst.pyx":2176
+  /* "pywrapfst.pyx":2198
  *                                                        weight)
  *     fst.Prune(self._mfst.get(), wc, nstate, delta)
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -25318,11 +24444,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__prune(struct __pyx_obj_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2176, __pyx_L1_error)
+    __PYX_ERR(0, 2198, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2176, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2198, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2170
+  /* "pywrapfst.pyx":2192
  *     return self
  * 
  *   cdef void _prune(self, float delta=fst.kDelta, int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
@@ -25338,7 +24464,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__prune(struct __pyx_obj_9pywrapfst_
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2178
+/* "pywrapfst.pyx":2200
  *     self._check_mutating_imethod()
  * 
  *   def prune(self,             # <<<<<<<<<<<<<<
@@ -25360,7 +24486,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_35prune(PyObject *__pyx_v_sel
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_delta,&__pyx_n_s_nstate,&__pyx_n_s_weight,0};
     PyObject* values[3] = {0,0,0};
 
-    /* "pywrapfst.pyx":2181
+    /* "pywrapfst.pyx":2203
  *             float delta=fst.kDelta,
  *             int64 nstate=fst.kNoStateId,
  *             weight=None):             # <<<<<<<<<<<<<<
@@ -25402,7 +24528,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_35prune(PyObject *__pyx_v_sel
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "prune") < 0)) __PYX_ERR(0, 2178, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "prune") < 0)) __PYX_ERR(0, 2200, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -25417,20 +24543,20 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_35prune(PyObject *__pyx_v_sel
       }
     }
     if (values[0]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 2179, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 2201, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__39;
+      __pyx_v_delta = __pyx_k__15;
     }
     if (values[1]) {
-      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2180, __pyx_L3_error)
+      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2202, __pyx_L3_error)
     } else {
-      __pyx_v_nstate = __pyx_k__40;
+      __pyx_v_nstate = __pyx_k__16;
     }
     __pyx_v_weight = values[2];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("prune", 0, 0, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2178, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("prune", 0, 0, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2200, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.prune", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -25438,7 +24564,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_35prune(PyObject *__pyx_v_sel
   __pyx_L4_argument_unpacking_done:;
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_34prune(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), __pyx_v_delta, __pyx_v_nstate, __pyx_v_weight);
 
-  /* "pywrapfst.pyx":2178
+  /* "pywrapfst.pyx":2200
  *     self._check_mutating_imethod()
  * 
  *   def prune(self,             # <<<<<<<<<<<<<<
@@ -25457,7 +24583,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_34prune(struct __pyx_obj_9pyw
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__prune __pyx_t_1;
   __Pyx_RefNannySetupContext("prune", 0);
 
-  /* "pywrapfst.pyx":2203
+  /* "pywrapfst.pyx":2225
  *     See also: The constructive variant.
  *     """
  *     self._prune(delta, nstate, weight)             # <<<<<<<<<<<<<<
@@ -25466,15 +24592,15 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_34prune(struct __pyx_obj_9pyw
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_prune");
-    __PYX_ERR(0, 2203, __pyx_L1_error)
+    __PYX_ERR(0, 2225, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 3;
   __pyx_t_1.delta = __pyx_v_delta;
   __pyx_t_1.nstate = __pyx_v_nstate;
   __pyx_t_1.weight = __pyx_v_weight;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_prune(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2203, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_prune(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2225, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2204
+  /* "pywrapfst.pyx":2226
  *     """
  *     self._prune(delta, nstate, weight)
  *     return self             # <<<<<<<<<<<<<<
@@ -25486,7 +24612,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_34prune(struct __pyx_obj_9pyw
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2178
+  /* "pywrapfst.pyx":2200
  *     self._check_mutating_imethod()
  * 
  *   def prune(self,             # <<<<<<<<<<<<<<
@@ -25504,7 +24630,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_34prune(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2206
+/* "pywrapfst.pyx":2228
  *     return self
  * 
  *   cdef void _push(self,             # <<<<<<<<<<<<<<
@@ -25513,9 +24639,9 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_34prune(struct __pyx_obj_9pyw
  */
 
 static void __pyx_f_9pywrapfst_11_MutableFst__push(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self, struct __pyx_opt_args_9pywrapfst_11_MutableFst__push *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__41;
+  float __pyx_v_delta = __pyx_k__17;
 
-  /* "pywrapfst.pyx":2208
+  /* "pywrapfst.pyx":2230
  *   cdef void _push(self,
  *                   float delta=fst.kDelta,
  *                   bool remove_total_weight=False,             # <<<<<<<<<<<<<<
@@ -25524,7 +24650,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__push(struct __pyx_obj_9pywrapfst__
  */
   bool __pyx_v_remove_total_weight = ((bool)0);
 
-  /* "pywrapfst.pyx":2209
+  /* "pywrapfst.pyx":2231
  *                   float delta=fst.kDelta,
  *                   bool remove_total_weight=False,
  *                   bool to_final=False) except *:             # <<<<<<<<<<<<<<
@@ -25546,7 +24672,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__push(struct __pyx_obj_9pywrapfst__
     }
   }
 
-  /* "pywrapfst.pyx":2210
+  /* "pywrapfst.pyx":2232
  *                   bool remove_total_weight=False,
  *                   bool to_final=False) except *:
  *     fst.Push(self._mfst.get(), fst.GetReweightType(to_final), delta,             # <<<<<<<<<<<<<<
@@ -25555,10 +24681,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__push(struct __pyx_obj_9pywrapfst__
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2210, __pyx_L1_error)
+    __PYX_ERR(0, 2232, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":2211
+  /* "pywrapfst.pyx":2233
  *                   bool to_final=False) except *:
  *     fst.Push(self._mfst.get(), fst.GetReweightType(to_final), delta,
  *              remove_total_weight)             # <<<<<<<<<<<<<<
@@ -25567,7 +24693,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__push(struct __pyx_obj_9pywrapfst__
  */
   fst::script::Push(__pyx_v_self->_mfst.get(), fst::script::GetReweightType(__pyx_v_to_final), __pyx_v_delta, __pyx_v_remove_total_weight);
 
-  /* "pywrapfst.pyx":2212
+  /* "pywrapfst.pyx":2234
  *     fst.Push(self._mfst.get(), fst.GetReweightType(to_final), delta,
  *              remove_total_weight)
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -25576,11 +24702,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__push(struct __pyx_obj_9pywrapfst__
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2212, __pyx_L1_error)
+    __PYX_ERR(0, 2234, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2212, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2234, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2206
+  /* "pywrapfst.pyx":2228
  *     return self
  * 
  *   cdef void _push(self,             # <<<<<<<<<<<<<<
@@ -25596,7 +24722,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__push(struct __pyx_obj_9pywrapfst__
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2214
+/* "pywrapfst.pyx":2236
  *     self._check_mutating_imethod()
  * 
  *   def push(self,             # <<<<<<<<<<<<<<
@@ -25651,7 +24777,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_37push(PyObject *__pyx_v_self
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "push") < 0)) __PYX_ERR(0, 2214, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "push") < 0)) __PYX_ERR(0, 2236, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -25666,15 +24792,15 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_37push(PyObject *__pyx_v_self
       }
     }
     if (values[0]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 2215, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 2237, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__42;
+      __pyx_v_delta = __pyx_k__18;
     }
     if (values[1]) {
-      __pyx_v_remove_total_weight = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_remove_total_weight == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2216, __pyx_L3_error)
+      __pyx_v_remove_total_weight = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_remove_total_weight == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2238, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":2216
+      /* "pywrapfst.pyx":2238
  *   def push(self,
  *            float delta=fst.kDelta,
  *            bool remove_total_weight=False,             # <<<<<<<<<<<<<<
@@ -25684,10 +24810,10 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_37push(PyObject *__pyx_v_self
       __pyx_v_remove_total_weight = ((bool)0);
     }
     if (values[2]) {
-      __pyx_v_to_final = __Pyx_PyObject_IsTrue(values[2]); if (unlikely((__pyx_v_to_final == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2217, __pyx_L3_error)
+      __pyx_v_to_final = __Pyx_PyObject_IsTrue(values[2]); if (unlikely((__pyx_v_to_final == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2239, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":2217
+      /* "pywrapfst.pyx":2239
  *            float delta=fst.kDelta,
  *            bool remove_total_weight=False,
  *            bool to_final=False):             # <<<<<<<<<<<<<<
@@ -25699,7 +24825,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_37push(PyObject *__pyx_v_self
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("push", 0, 0, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2214, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("push", 0, 0, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2236, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.push", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -25707,7 +24833,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_37push(PyObject *__pyx_v_self
   __pyx_L4_argument_unpacking_done:;
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_36push(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), __pyx_v_delta, __pyx_v_remove_total_weight, __pyx_v_to_final);
 
-  /* "pywrapfst.pyx":2214
+  /* "pywrapfst.pyx":2236
  *     self._check_mutating_imethod()
  * 
  *   def push(self,             # <<<<<<<<<<<<<<
@@ -25726,7 +24852,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_36push(struct __pyx_obj_9pywr
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__push __pyx_t_1;
   __Pyx_RefNannySetupContext("push", 0);
 
-  /* "pywrapfst.pyx":2243
+  /* "pywrapfst.pyx":2265
  *     See also: The constructive variant, which also supports label pushing.
  *     """
  *     self._push(delta, remove_total_weight, to_final)             # <<<<<<<<<<<<<<
@@ -25735,15 +24861,15 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_36push(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_push");
-    __PYX_ERR(0, 2243, __pyx_L1_error)
+    __PYX_ERR(0, 2265, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 3;
   __pyx_t_1.delta = __pyx_v_delta;
   __pyx_t_1.remove_total_weight = __pyx_v_remove_total_weight;
   __pyx_t_1.to_final = __pyx_v_to_final;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_push(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2243, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_push(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2265, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2244
+  /* "pywrapfst.pyx":2266
  *     """
  *     self._push(delta, remove_total_weight, to_final)
  *     return self             # <<<<<<<<<<<<<<
@@ -25755,7 +24881,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_36push(struct __pyx_obj_9pywr
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2214
+  /* "pywrapfst.pyx":2236
  *     self._check_mutating_imethod()
  * 
  *   def push(self,             # <<<<<<<<<<<<<<
@@ -25773,7 +24899,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_36push(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2246
+/* "pywrapfst.pyx":2268
  *     return self
  * 
  *   cdef void _relabel_pairs(self, ipairs=None, opairs=None) except *:             # <<<<<<<<<<<<<<
@@ -25813,7 +24939,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
     }
   }
 
-  /* "pywrapfst.pyx":2248
+  /* "pywrapfst.pyx":2270
  *   cdef void _relabel_pairs(self, ipairs=None, opairs=None) except *:
  *     cdef unique_ptr[vector[fst.LabelPair]] _ipairs
  *     _ipairs.reset(new vector[fst.LabelPair]())             # <<<<<<<<<<<<<<
@@ -25824,11 +24950,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
     __pyx_t_1 = new std::vector<__pyx_t_3fst_LabelPair> ();
   } catch(...) {
     __Pyx_CppExn2PyErr();
-    __PYX_ERR(0, 2248, __pyx_L1_error)
+    __PYX_ERR(0, 2270, __pyx_L1_error)
   }
   __pyx_v__ipairs.reset(__pyx_t_1);
 
-  /* "pywrapfst.pyx":2250
+  /* "pywrapfst.pyx":2272
  *     _ipairs.reset(new vector[fst.LabelPair]())
  *     cdef unique_ptr[vector[fst.LabelPair]] _opairs
  *     _opairs.reset(new vector[fst.LabelPair]())             # <<<<<<<<<<<<<<
@@ -25839,21 +24965,21 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
     __pyx_t_1 = new std::vector<__pyx_t_3fst_LabelPair> ();
   } catch(...) {
     __Pyx_CppExn2PyErr();
-    __PYX_ERR(0, 2250, __pyx_L1_error)
+    __PYX_ERR(0, 2272, __pyx_L1_error)
   }
   __pyx_v__opairs.reset(__pyx_t_1);
 
-  /* "pywrapfst.pyx":2253
+  /* "pywrapfst.pyx":2275
  *     cdef int64 before
  *     cdef int64 after
  *     if ipairs:             # <<<<<<<<<<<<<<
  *       for (before, after) in ipairs:
  *         _ipairs.get().push_back(fst.LabelPair(before, after))
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_ipairs); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 2253, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_ipairs); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 2275, __pyx_L1_error)
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":2254
+    /* "pywrapfst.pyx":2276
  *     cdef int64 after
  *     if ipairs:
  *       for (before, after) in ipairs:             # <<<<<<<<<<<<<<
@@ -25864,26 +24990,26 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
       __pyx_t_3 = __pyx_v_ipairs; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
       __pyx_t_5 = NULL;
     } else {
-      __pyx_t_4 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_ipairs); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2254, __pyx_L1_error)
+      __pyx_t_4 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_ipairs); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2276, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2254, __pyx_L1_error)
+      __pyx_t_5 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2276, __pyx_L1_error)
     }
     for (;;) {
       if (likely(!__pyx_t_5)) {
         if (likely(PyList_CheckExact(__pyx_t_3))) {
           if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
           #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-          __pyx_t_6 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 2254, __pyx_L1_error)
+          __pyx_t_6 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 2276, __pyx_L1_error)
           #else
-          __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2254, __pyx_L1_error)
+          __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2276, __pyx_L1_error)
           __Pyx_GOTREF(__pyx_t_6);
           #endif
         } else {
           if (__pyx_t_4 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
           #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-          __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 2254, __pyx_L1_error)
+          __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 2276, __pyx_L1_error)
           #else
-          __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2254, __pyx_L1_error)
+          __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2276, __pyx_L1_error)
           __Pyx_GOTREF(__pyx_t_6);
           #endif
         }
@@ -25893,7 +25019,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
           PyObject* exc_type = PyErr_Occurred();
           if (exc_type) {
             if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-            else __PYX_ERR(0, 2254, __pyx_L1_error)
+            else __PYX_ERR(0, 2276, __pyx_L1_error)
           }
           break;
         }
@@ -25905,7 +25031,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         if (unlikely(size != 2)) {
           if (size > 2) __Pyx_RaiseTooManyValuesError(2);
           else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-          __PYX_ERR(0, 2254, __pyx_L1_error)
+          __PYX_ERR(0, 2276, __pyx_L1_error)
         }
         #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
         if (likely(PyTuple_CheckExact(sequence))) {
@@ -25918,15 +25044,15 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         __Pyx_INCREF(__pyx_t_7);
         __Pyx_INCREF(__pyx_t_8);
         #else
-        __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2254, __pyx_L1_error)
+        __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2276, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_7);
-        __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2254, __pyx_L1_error)
+        __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2276, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_8);
         #endif
         __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
       } else {
         Py_ssize_t index = -1;
-        __pyx_t_9 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2254, __pyx_L1_error)
+        __pyx_t_9 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2276, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_9);
         __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
         __pyx_t_10 = Py_TYPE(__pyx_t_9)->tp_iternext;
@@ -25934,7 +25060,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         __Pyx_GOTREF(__pyx_t_7);
         index = 1; __pyx_t_8 = __pyx_t_10(__pyx_t_9); if (unlikely(!__pyx_t_8)) goto __pyx_L6_unpacking_failed;
         __Pyx_GOTREF(__pyx_t_8);
-        if (__Pyx_IternextUnpackEndCheck(__pyx_t_10(__pyx_t_9), 2) < 0) __PYX_ERR(0, 2254, __pyx_L1_error)
+        if (__Pyx_IternextUnpackEndCheck(__pyx_t_10(__pyx_t_9), 2) < 0) __PYX_ERR(0, 2276, __pyx_L1_error)
         __pyx_t_10 = NULL;
         __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
         goto __pyx_L7_unpacking_done;
@@ -25942,17 +25068,17 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
         __pyx_t_10 = NULL;
         if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-        __PYX_ERR(0, 2254, __pyx_L1_error)
+        __PYX_ERR(0, 2276, __pyx_L1_error)
         __pyx_L7_unpacking_done:;
       }
-      __pyx_t_11 = __Pyx_PyInt_As_int64_t(__pyx_t_7); if (unlikely((__pyx_t_11 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2254, __pyx_L1_error)
+      __pyx_t_11 = __Pyx_PyInt_As_int64_t(__pyx_t_7); if (unlikely((__pyx_t_11 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2276, __pyx_L1_error)
       __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      __pyx_t_12 = __Pyx_PyInt_As_int64_t(__pyx_t_8); if (unlikely((__pyx_t_12 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2254, __pyx_L1_error)
+      __pyx_t_12 = __Pyx_PyInt_As_int64_t(__pyx_t_8); if (unlikely((__pyx_t_12 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2276, __pyx_L1_error)
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
       __pyx_v_before = __pyx_t_11;
       __pyx_v_after = __pyx_t_12;
 
-      /* "pywrapfst.pyx":2255
+      /* "pywrapfst.pyx":2277
  *     if ipairs:
  *       for (before, after) in ipairs:
  *         _ipairs.get().push_back(fst.LabelPair(before, after))             # <<<<<<<<<<<<<<
@@ -25963,16 +25089,16 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         __pyx_t_13 = __pyx_t_3fst_LabelPair(__pyx_v_before, __pyx_v_after);
       } catch(...) {
         __Pyx_CppExn2PyErr();
-        __PYX_ERR(0, 2255, __pyx_L1_error)
+        __PYX_ERR(0, 2277, __pyx_L1_error)
       }
       try {
         __pyx_v__ipairs.get()->push_back(__pyx_t_13);
       } catch(...) {
         __Pyx_CppExn2PyErr();
-        __PYX_ERR(0, 2255, __pyx_L1_error)
+        __PYX_ERR(0, 2277, __pyx_L1_error)
       }
 
-      /* "pywrapfst.pyx":2254
+      /* "pywrapfst.pyx":2276
  *     cdef int64 after
  *     if ipairs:
  *       for (before, after) in ipairs:             # <<<<<<<<<<<<<<
@@ -25982,7 +25108,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
     }
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-    /* "pywrapfst.pyx":2253
+    /* "pywrapfst.pyx":2275
  *     cdef int64 before
  *     cdef int64 after
  *     if ipairs:             # <<<<<<<<<<<<<<
@@ -25991,17 +25117,17 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
  */
   }
 
-  /* "pywrapfst.pyx":2256
+  /* "pywrapfst.pyx":2278
  *       for (before, after) in ipairs:
  *         _ipairs.get().push_back(fst.LabelPair(before, after))
  *     if opairs:             # <<<<<<<<<<<<<<
  *       for (before, after) in opairs:
  *         _opairs.get().push_back(fst.LabelPair(before, after))
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_opairs); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 2256, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_opairs); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 2278, __pyx_L1_error)
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":2257
+    /* "pywrapfst.pyx":2279
  *         _ipairs.get().push_back(fst.LabelPair(before, after))
  *     if opairs:
  *       for (before, after) in opairs:             # <<<<<<<<<<<<<<
@@ -26012,26 +25138,26 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
       __pyx_t_3 = __pyx_v_opairs; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
       __pyx_t_5 = NULL;
     } else {
-      __pyx_t_4 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_opairs); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2257, __pyx_L1_error)
+      __pyx_t_4 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_opairs); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2279, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_5 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2257, __pyx_L1_error)
+      __pyx_t_5 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2279, __pyx_L1_error)
     }
     for (;;) {
       if (likely(!__pyx_t_5)) {
         if (likely(PyList_CheckExact(__pyx_t_3))) {
           if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
           #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-          __pyx_t_6 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 2257, __pyx_L1_error)
+          __pyx_t_6 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 2279, __pyx_L1_error)
           #else
-          __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2257, __pyx_L1_error)
+          __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2279, __pyx_L1_error)
           __Pyx_GOTREF(__pyx_t_6);
           #endif
         } else {
           if (__pyx_t_4 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
           #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-          __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 2257, __pyx_L1_error)
+          __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_6); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 2279, __pyx_L1_error)
           #else
-          __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2257, __pyx_L1_error)
+          __pyx_t_6 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2279, __pyx_L1_error)
           __Pyx_GOTREF(__pyx_t_6);
           #endif
         }
@@ -26041,7 +25167,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
           PyObject* exc_type = PyErr_Occurred();
           if (exc_type) {
             if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-            else __PYX_ERR(0, 2257, __pyx_L1_error)
+            else __PYX_ERR(0, 2279, __pyx_L1_error)
           }
           break;
         }
@@ -26053,7 +25179,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         if (unlikely(size != 2)) {
           if (size > 2) __Pyx_RaiseTooManyValuesError(2);
           else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-          __PYX_ERR(0, 2257, __pyx_L1_error)
+          __PYX_ERR(0, 2279, __pyx_L1_error)
         }
         #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
         if (likely(PyTuple_CheckExact(sequence))) {
@@ -26066,15 +25192,15 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         __Pyx_INCREF(__pyx_t_8);
         __Pyx_INCREF(__pyx_t_7);
         #else
-        __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2257, __pyx_L1_error)
+        __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2279, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_8);
-        __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2257, __pyx_L1_error)
+        __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2279, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_7);
         #endif
         __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
       } else {
         Py_ssize_t index = -1;
-        __pyx_t_9 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2257, __pyx_L1_error)
+        __pyx_t_9 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2279, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_9);
         __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
         __pyx_t_10 = Py_TYPE(__pyx_t_9)->tp_iternext;
@@ -26082,7 +25208,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         __Pyx_GOTREF(__pyx_t_8);
         index = 1; __pyx_t_7 = __pyx_t_10(__pyx_t_9); if (unlikely(!__pyx_t_7)) goto __pyx_L11_unpacking_failed;
         __Pyx_GOTREF(__pyx_t_7);
-        if (__Pyx_IternextUnpackEndCheck(__pyx_t_10(__pyx_t_9), 2) < 0) __PYX_ERR(0, 2257, __pyx_L1_error)
+        if (__Pyx_IternextUnpackEndCheck(__pyx_t_10(__pyx_t_9), 2) < 0) __PYX_ERR(0, 2279, __pyx_L1_error)
         __pyx_t_10 = NULL;
         __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
         goto __pyx_L12_unpacking_done;
@@ -26090,17 +25216,17 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
         __pyx_t_10 = NULL;
         if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-        __PYX_ERR(0, 2257, __pyx_L1_error)
+        __PYX_ERR(0, 2279, __pyx_L1_error)
         __pyx_L12_unpacking_done:;
       }
-      __pyx_t_12 = __Pyx_PyInt_As_int64_t(__pyx_t_8); if (unlikely((__pyx_t_12 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2257, __pyx_L1_error)
+      __pyx_t_12 = __Pyx_PyInt_As_int64_t(__pyx_t_8); if (unlikely((__pyx_t_12 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2279, __pyx_L1_error)
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __pyx_t_11 = __Pyx_PyInt_As_int64_t(__pyx_t_7); if (unlikely((__pyx_t_11 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2257, __pyx_L1_error)
+      __pyx_t_11 = __Pyx_PyInt_As_int64_t(__pyx_t_7); if (unlikely((__pyx_t_11 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2279, __pyx_L1_error)
       __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
       __pyx_v_before = __pyx_t_12;
       __pyx_v_after = __pyx_t_11;
 
-      /* "pywrapfst.pyx":2258
+      /* "pywrapfst.pyx":2280
  *     if opairs:
  *       for (before, after) in opairs:
  *         _opairs.get().push_back(fst.LabelPair(before, after))             # <<<<<<<<<<<<<<
@@ -26111,16 +25237,16 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
         __pyx_t_13 = __pyx_t_3fst_LabelPair(__pyx_v_before, __pyx_v_after);
       } catch(...) {
         __Pyx_CppExn2PyErr();
-        __PYX_ERR(0, 2258, __pyx_L1_error)
+        __PYX_ERR(0, 2280, __pyx_L1_error)
       }
       try {
         __pyx_v__opairs.get()->push_back(__pyx_t_13);
       } catch(...) {
         __Pyx_CppExn2PyErr();
-        __PYX_ERR(0, 2258, __pyx_L1_error)
+        __PYX_ERR(0, 2280, __pyx_L1_error)
       }
 
-      /* "pywrapfst.pyx":2257
+      /* "pywrapfst.pyx":2279
  *         _ipairs.get().push_back(fst.LabelPair(before, after))
  *     if opairs:
  *       for (before, after) in opairs:             # <<<<<<<<<<<<<<
@@ -26130,7 +25256,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
     }
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-    /* "pywrapfst.pyx":2256
+    /* "pywrapfst.pyx":2278
  *       for (before, after) in ipairs:
  *         _ipairs.get().push_back(fst.LabelPair(before, after))
  *     if opairs:             # <<<<<<<<<<<<<<
@@ -26139,7 +25265,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
  */
   }
 
-  /* "pywrapfst.pyx":2259
+  /* "pywrapfst.pyx":2281
  *       for (before, after) in opairs:
  *         _opairs.get().push_back(fst.LabelPair(before, after))
  *     if _ipairs.get().empty() and _opairs.get().empty():             # <<<<<<<<<<<<<<
@@ -26157,23 +25283,35 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
   __pyx_L14_bool_binop_done:;
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":2260
+    /* "pywrapfst.pyx":2282
  *         _opairs.get().push_back(fst.LabelPair(before, after))
  *     if _ipairs.get().empty() and _opairs.get().empty():
  *       raise FstArgError("No relabeling pairs specified.")             # <<<<<<<<<<<<<<
  *     fst.Relabel(self._mfst.get(), deref(_ipairs), deref(_opairs))
  *     self._check_mutating_imethod()
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2260, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple__43, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2260, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2282, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_Raise(__pyx_t_6, 0, 0, 0);
+    __pyx_t_7 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) {
+      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6);
+      if (likely(__pyx_t_7)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
+        __Pyx_INCREF(__pyx_t_7);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_6, function);
+      }
+    }
+    __pyx_t_3 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_kp_u_No_relabeling_pairs_specified) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_kp_u_No_relabeling_pairs_specified);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2282, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __PYX_ERR(0, 2260, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __PYX_ERR(0, 2282, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2259
+    /* "pywrapfst.pyx":2281
  *       for (before, after) in opairs:
  *         _opairs.get().push_back(fst.LabelPair(before, after))
  *     if _ipairs.get().empty() and _opairs.get().empty():             # <<<<<<<<<<<<<<
@@ -26182,7 +25320,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
  */
   }
 
-  /* "pywrapfst.pyx":2261
+  /* "pywrapfst.pyx":2283
  *     if _ipairs.get().empty() and _opairs.get().empty():
  *       raise FstArgError("No relabeling pairs specified.")
  *     fst.Relabel(self._mfst.get(), deref(_ipairs), deref(_opairs))             # <<<<<<<<<<<<<<
@@ -26191,11 +25329,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2261, __pyx_L1_error)
+    __PYX_ERR(0, 2283, __pyx_L1_error)
   }
   fst::script::Relabel(__pyx_v_self->_mfst.get(), (*__pyx_v__ipairs), (*__pyx_v__opairs));
 
-  /* "pywrapfst.pyx":2262
+  /* "pywrapfst.pyx":2284
  *       raise FstArgError("No relabeling pairs specified.")
  *     fst.Relabel(self._mfst.get(), deref(_ipairs), deref(_opairs))
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -26204,11 +25342,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2262, __pyx_L1_error)
+    __PYX_ERR(0, 2284, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2262, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2284, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2246
+  /* "pywrapfst.pyx":2268
  *     return self
  * 
  *   cdef void _relabel_pairs(self, ipairs=None, opairs=None) except *:             # <<<<<<<<<<<<<<
@@ -26229,7 +25367,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_pairs(struct __pyx_obj_9py
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2264
+/* "pywrapfst.pyx":2286
  *     self._check_mutating_imethod()
  * 
  *   def relabel_pairs(self, ipairs=None, opairs=None):             # <<<<<<<<<<<<<<
@@ -26277,7 +25415,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_39relabel_pairs(PyObject *__p
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "relabel_pairs") < 0)) __PYX_ERR(0, 2264, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "relabel_pairs") < 0)) __PYX_ERR(0, 2286, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -26294,7 +25432,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_39relabel_pairs(PyObject *__p
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("relabel_pairs", 0, 0, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2264, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("relabel_pairs", 0, 0, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2286, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.relabel_pairs", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -26313,7 +25451,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_38relabel_pairs(struct __pyx_
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__relabel_pairs __pyx_t_1;
   __Pyx_RefNannySetupContext("relabel_pairs", 0);
 
-  /* "pywrapfst.pyx":2286
+  /* "pywrapfst.pyx":2308
  *     See also: `decode`, `encode`, `project`, `relabel_tables`.
  *     """
  *     self._relabel_pairs(ipairs, opairs)             # <<<<<<<<<<<<<<
@@ -26322,14 +25460,14 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_38relabel_pairs(struct __pyx_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_relabel_pairs");
-    __PYX_ERR(0, 2286, __pyx_L1_error)
+    __PYX_ERR(0, 2308, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 2;
   __pyx_t_1.ipairs = __pyx_v_ipairs;
   __pyx_t_1.opairs = __pyx_v_opairs;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_relabel_pairs(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2286, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_relabel_pairs(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2308, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2287
+  /* "pywrapfst.pyx":2309
  *     """
  *     self._relabel_pairs(ipairs, opairs)
  *     return self             # <<<<<<<<<<<<<<
@@ -26341,7 +25479,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_38relabel_pairs(struct __pyx_
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2264
+  /* "pywrapfst.pyx":2286
  *     self._check_mutating_imethod()
  * 
  *   def relabel_pairs(self, ipairs=None, opairs=None):             # <<<<<<<<<<<<<<
@@ -26359,7 +25497,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_38relabel_pairs(struct __pyx_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2289
+/* "pywrapfst.pyx":2311
  *     return self
  * 
  *   cdef void _relabel_tables(self,             # <<<<<<<<<<<<<<
@@ -26369,7 +25507,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_38relabel_pairs(struct __pyx_
 
 static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self, struct __pyx_opt_args_9pywrapfst_11_MutableFst__relabel_tables *__pyx_optional_args) {
 
-  /* "pywrapfst.pyx":2290
+  /* "pywrapfst.pyx":2312
  * 
  *   cdef void _relabel_tables(self,
  *                             _SymbolTable old_isymbols=None,             # <<<<<<<<<<<<<<
@@ -26378,7 +25516,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_old_isymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-  /* "pywrapfst.pyx":2291
+  /* "pywrapfst.pyx":2313
  *   cdef void _relabel_tables(self,
  *                             _SymbolTable old_isymbols=None,
  *                             _SymbolTable new_isymbols=None,             # <<<<<<<<<<<<<<
@@ -26386,9 +25524,9 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  *                             bool attach_new_isymbols=True,
  */
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_new_isymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
-  PyObject *__pyx_v_unknown_isymbol = ((PyObject *)__pyx_kp_b__24);
+  PyObject *__pyx_v_unknown_isymbol = ((PyObject *)__pyx_kp_b__10);
 
-  /* "pywrapfst.pyx":2293
+  /* "pywrapfst.pyx":2315
  *                             _SymbolTable new_isymbols=None,
  *                             unknown_isymbol=b"",
  *                             bool attach_new_isymbols=True,             # <<<<<<<<<<<<<<
@@ -26397,7 +25535,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   bool __pyx_v_attach_new_isymbols = ((bool)1);
 
-  /* "pywrapfst.pyx":2294
+  /* "pywrapfst.pyx":2316
  *                             unknown_isymbol=b"",
  *                             bool attach_new_isymbols=True,
  *                             _SymbolTable old_osymbols=None,             # <<<<<<<<<<<<<<
@@ -26406,7 +25544,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_old_osymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-  /* "pywrapfst.pyx":2295
+  /* "pywrapfst.pyx":2317
  *                             bool attach_new_isymbols=True,
  *                             _SymbolTable old_osymbols=None,
  *                             _SymbolTable new_osymbols=None,             # <<<<<<<<<<<<<<
@@ -26414,9 +25552,9 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  *                             bool attach_new_osymbols=True) except *:
  */
   struct __pyx_obj_9pywrapfst__SymbolTable *__pyx_v_new_osymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
-  PyObject *__pyx_v_unknown_osymbol = ((PyObject *)__pyx_kp_b__24);
+  PyObject *__pyx_v_unknown_osymbol = ((PyObject *)__pyx_kp_b__10);
 
-  /* "pywrapfst.pyx":2297
+  /* "pywrapfst.pyx":2319
  *                             _SymbolTable new_osymbols=None,
  *                             unknown_osymbol=b"",
  *                             bool attach_new_osymbols=True) except *:             # <<<<<<<<<<<<<<
@@ -26432,11 +25570,12 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
   int __pyx_t_3;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  fst::SymbolTable *__pyx_t_6;
-  fst::SymbolTable const *__pyx_t_7;
-  std::string __pyx_t_8;
-  fst::SymbolTable const *__pyx_t_9;
-  std::string __pyx_t_10;
+  PyObject *__pyx_t_6 = NULL;
+  fst::SymbolTable *__pyx_t_7;
+  fst::SymbolTable const *__pyx_t_8;
+  std::string __pyx_t_9;
+  fst::SymbolTable const *__pyx_t_10;
+  std::string __pyx_t_11;
   __Pyx_RefNannySetupContext("_relabel_tables", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -26465,7 +25604,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
     }
   }
 
-  /* "pywrapfst.pyx":2298
+  /* "pywrapfst.pyx":2320
  *                             unknown_osymbol=b"",
  *                             bool attach_new_osymbols=True) except *:
  *     if new_isymbols is None and new_osymbols is None:             # <<<<<<<<<<<<<<
@@ -26485,23 +25624,35 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
   __pyx_L4_bool_binop_done:;
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":2299
+    /* "pywrapfst.pyx":2321
  *                             bool attach_new_osymbols=True) except *:
  *     if new_isymbols is None and new_osymbols is None:
  *       raise FstArgError("No new SymbolTables specified")             # <<<<<<<<<<<<<<
  *     cdef fst.SymbolTable *new_isymbols_ptr = NULL
  *     if new_isymbols is not None:
  */
-    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2299, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_tuple__44, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2299, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2321, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_Raise(__pyx_t_5, 0, 0, 0);
+    __pyx_t_6 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
+      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+      if (likely(__pyx_t_6)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_6);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_5, function);
+      }
+    }
+    __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_6, __pyx_kp_u_No_new_SymbolTables_specified) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_kp_u_No_new_SymbolTables_specified);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2321, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __PYX_ERR(0, 2299, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __PYX_ERR(0, 2321, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2298
+    /* "pywrapfst.pyx":2320
  *                             unknown_osymbol=b"",
  *                             bool attach_new_osymbols=True) except *:
  *     if new_isymbols is None and new_osymbols is None:             # <<<<<<<<<<<<<<
@@ -26510,7 +25661,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   }
 
-  /* "pywrapfst.pyx":2300
+  /* "pywrapfst.pyx":2322
  *     if new_isymbols is None and new_osymbols is None:
  *       raise FstArgError("No new SymbolTables specified")
  *     cdef fst.SymbolTable *new_isymbols_ptr = NULL             # <<<<<<<<<<<<<<
@@ -26519,7 +25670,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   __pyx_v_new_isymbols_ptr = NULL;
 
-  /* "pywrapfst.pyx":2301
+  /* "pywrapfst.pyx":2323
  *       raise FstArgError("No new SymbolTables specified")
  *     cdef fst.SymbolTable *new_isymbols_ptr = NULL
  *     if new_isymbols is not None:             # <<<<<<<<<<<<<<
@@ -26530,7 +25681,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
   __pyx_t_2 = (__pyx_t_1 != 0);
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":2302
+    /* "pywrapfst.pyx":2324
  *     cdef fst.SymbolTable *new_isymbols_ptr = NULL
  *     if new_isymbols is not None:
  *       new_isymbols_ptr = new_isymbols._table             # <<<<<<<<<<<<<<
@@ -26539,12 +25690,12 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
     if (unlikely(((PyObject *)__pyx_v_new_isymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 2302, __pyx_L1_error)
+      __PYX_ERR(0, 2324, __pyx_L1_error)
     }
-    __pyx_t_6 = __pyx_v_new_isymbols->_table;
-    __pyx_v_new_isymbols_ptr = __pyx_t_6;
+    __pyx_t_7 = __pyx_v_new_isymbols->_table;
+    __pyx_v_new_isymbols_ptr = __pyx_t_7;
 
-    /* "pywrapfst.pyx":2301
+    /* "pywrapfst.pyx":2323
  *       raise FstArgError("No new SymbolTables specified")
  *     cdef fst.SymbolTable *new_isymbols_ptr = NULL
  *     if new_isymbols is not None:             # <<<<<<<<<<<<<<
@@ -26553,7 +25704,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   }
 
-  /* "pywrapfst.pyx":2303
+  /* "pywrapfst.pyx":2325
  *     if new_isymbols is not None:
  *       new_isymbols_ptr = new_isymbols._table
  *     cdef fst.SymbolTable *new_osymbols_ptr = NULL             # <<<<<<<<<<<<<<
@@ -26562,7 +25713,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   __pyx_v_new_osymbols_ptr = NULL;
 
-  /* "pywrapfst.pyx":2304
+  /* "pywrapfst.pyx":2326
  *       new_isymbols_ptr = new_isymbols._table
  *     cdef fst.SymbolTable *new_osymbols_ptr = NULL
  *     if new_osymbols is not None:             # <<<<<<<<<<<<<<
@@ -26573,7 +25724,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
   __pyx_t_1 = (__pyx_t_2 != 0);
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":2305
+    /* "pywrapfst.pyx":2327
  *     cdef fst.SymbolTable *new_osymbols_ptr = NULL
  *     if new_osymbols is not None:
  *       new_osymbols_ptr = new_osymbols._table             # <<<<<<<<<<<<<<
@@ -26582,12 +25733,12 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
     if (unlikely(((PyObject *)__pyx_v_new_osymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 2305, __pyx_L1_error)
+      __PYX_ERR(0, 2327, __pyx_L1_error)
     }
-    __pyx_t_6 = __pyx_v_new_osymbols->_table;
-    __pyx_v_new_osymbols_ptr = __pyx_t_6;
+    __pyx_t_7 = __pyx_v_new_osymbols->_table;
+    __pyx_v_new_osymbols_ptr = __pyx_t_7;
 
-    /* "pywrapfst.pyx":2304
+    /* "pywrapfst.pyx":2326
  *       new_isymbols_ptr = new_isymbols._table
  *     cdef fst.SymbolTable *new_osymbols_ptr = NULL
  *     if new_osymbols is not None:             # <<<<<<<<<<<<<<
@@ -26596,7 +25747,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   }
 
-  /* "pywrapfst.pyx":2306
+  /* "pywrapfst.pyx":2328
  *     if new_osymbols is not None:
  *       new_osymbols_ptr = new_osymbols._table
  *     fst.Relabel(self._mfst.get(),             # <<<<<<<<<<<<<<
@@ -26605,10 +25756,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2306, __pyx_L1_error)
+    __PYX_ERR(0, 2328, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":2307
+  /* "pywrapfst.pyx":2329
  *       new_osymbols_ptr = new_osymbols._table
  *     fst.Relabel(self._mfst.get(),
  *         self._fst.get().InputSymbols() if old_isymbols is None else             # <<<<<<<<<<<<<<
@@ -26619,12 +25770,12 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
   if ((__pyx_t_1 != 0)) {
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-      __PYX_ERR(0, 2307, __pyx_L1_error)
+      __PYX_ERR(0, 2329, __pyx_L1_error)
     }
-    __pyx_t_7 = __pyx_v_self->__pyx_base._fst.get()->InputSymbols();
+    __pyx_t_8 = __pyx_v_self->__pyx_base._fst.get()->InputSymbols();
   } else {
 
-    /* "pywrapfst.pyx":2308
+    /* "pywrapfst.pyx":2330
  *     fst.Relabel(self._mfst.get(),
  *         self._fst.get().InputSymbols() if old_isymbols is None else
  *         old_isymbols._table, new_isymbols_ptr, tostring(unknown_isymbol),             # <<<<<<<<<<<<<<
@@ -26633,13 +25784,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
     if (unlikely(((PyObject *)__pyx_v_old_isymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 2308, __pyx_L1_error)
+      __PYX_ERR(0, 2330, __pyx_L1_error)
     }
-    __pyx_t_7 = __pyx_v_old_isymbols->_table;
+    __pyx_t_8 = __pyx_v_old_isymbols->_table;
   }
-  __pyx_t_8 = __pyx_f_9pywrapfst_tostring(__pyx_v_unknown_isymbol, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2308, __pyx_L1_error)
+  __pyx_t_9 = __pyx_f_9pywrapfst_tostring(__pyx_v_unknown_isymbol, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2330, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2310
+  /* "pywrapfst.pyx":2332
  *         old_isymbols._table, new_isymbols_ptr, tostring(unknown_isymbol),
  *         attach_new_isymbols,
  *         self._fst.get().OutputSymbols() if old_osymbols is None else             # <<<<<<<<<<<<<<
@@ -26650,12 +25801,12 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
   if ((__pyx_t_1 != 0)) {
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-      __PYX_ERR(0, 2310, __pyx_L1_error)
+      __PYX_ERR(0, 2332, __pyx_L1_error)
     }
-    __pyx_t_9 = __pyx_v_self->__pyx_base._fst.get()->OutputSymbols();
+    __pyx_t_10 = __pyx_v_self->__pyx_base._fst.get()->OutputSymbols();
   } else {
 
-    /* "pywrapfst.pyx":2311
+    /* "pywrapfst.pyx":2333
  *         attach_new_isymbols,
  *         self._fst.get().OutputSymbols() if old_osymbols is None else
  *         old_osymbols._table, new_osymbols_ptr, tostring(unknown_osymbol),             # <<<<<<<<<<<<<<
@@ -26664,22 +25815,22 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
     if (unlikely(((PyObject *)__pyx_v_old_osymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 2311, __pyx_L1_error)
+      __PYX_ERR(0, 2333, __pyx_L1_error)
     }
-    __pyx_t_9 = __pyx_v_old_osymbols->_table;
+    __pyx_t_10 = __pyx_v_old_osymbols->_table;
   }
-  __pyx_t_10 = __pyx_f_9pywrapfst_tostring(__pyx_v_unknown_osymbol, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2311, __pyx_L1_error)
+  __pyx_t_11 = __pyx_f_9pywrapfst_tostring(__pyx_v_unknown_osymbol, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2333, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2306
+  /* "pywrapfst.pyx":2328
  *     if new_osymbols is not None:
  *       new_osymbols_ptr = new_osymbols._table
  *     fst.Relabel(self._mfst.get(),             # <<<<<<<<<<<<<<
  *         self._fst.get().InputSymbols() if old_isymbols is None else
  *         old_isymbols._table, new_isymbols_ptr, tostring(unknown_isymbol),
  */
-  fst::script::Relabel(__pyx_v_self->_mfst.get(), __pyx_t_7, __pyx_v_new_isymbols_ptr, __pyx_t_8, __pyx_v_attach_new_isymbols, __pyx_t_9, __pyx_v_new_osymbols_ptr, __pyx_t_10, __pyx_v_attach_new_osymbols);
+  fst::script::Relabel(__pyx_v_self->_mfst.get(), __pyx_t_8, __pyx_v_new_isymbols_ptr, __pyx_t_9, __pyx_v_attach_new_isymbols, __pyx_t_10, __pyx_v_new_osymbols_ptr, __pyx_t_11, __pyx_v_attach_new_osymbols);
 
-  /* "pywrapfst.pyx":2313
+  /* "pywrapfst.pyx":2335
  *         old_osymbols._table, new_osymbols_ptr, tostring(unknown_osymbol),
  *         attach_new_osymbols)
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -26688,11 +25839,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2313, __pyx_L1_error)
+    __PYX_ERR(0, 2335, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2313, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2335, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2289
+  /* "pywrapfst.pyx":2311
  *     return self
  * 
  *   cdef void _relabel_tables(self,             # <<<<<<<<<<<<<<
@@ -26705,12 +25856,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__relabel_tables(struct __pyx_obj_9p
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_AddTraceback("pywrapfst._MutableFst._relabel_tables", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2315
+/* "pywrapfst.pyx":2337
  *     self._check_mutating_imethod()
  * 
  *   def relabel_tables(self,             # <<<<<<<<<<<<<<
@@ -26737,7 +25889,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables(PyObject *__
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_old_isymbols,&__pyx_n_s_new_isymbols,&__pyx_n_s_unknown_isymbol,&__pyx_n_s_attach_new_isymbols,&__pyx_n_s_old_osymbols,&__pyx_n_s_new_osymbols,&__pyx_n_s_unknown_osymbol,&__pyx_n_s_attach_new_osymbols,0};
     PyObject* values[8] = {0,0,0,0,0,0,0,0};
 
-    /* "pywrapfst.pyx":2316
+    /* "pywrapfst.pyx":2338
  * 
  *   def relabel_tables(self,
  *                      _SymbolTable old_isymbols=None,             # <<<<<<<<<<<<<<
@@ -26746,7 +25898,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables(PyObject *__
  */
     values[0] = (PyObject *)((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-    /* "pywrapfst.pyx":2317
+    /* "pywrapfst.pyx":2339
  *   def relabel_tables(self,
  *                      _SymbolTable old_isymbols=None,
  *                      _SymbolTable new_isymbols=None,             # <<<<<<<<<<<<<<
@@ -26754,9 +25906,9 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables(PyObject *__
  *                      bool attach_new_isymbols=True,
  */
     values[1] = (PyObject *)((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
-    values[2] = ((PyObject *)__pyx_kp_b__24);
+    values[2] = ((PyObject *)__pyx_kp_b__10);
 
-    /* "pywrapfst.pyx":2320
+    /* "pywrapfst.pyx":2342
  *                      unknown_isymbol=b"",
  *                      bool attach_new_isymbols=True,
  *                      _SymbolTable old_osymbols=None,             # <<<<<<<<<<<<<<
@@ -26765,7 +25917,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables(PyObject *__
  */
     values[4] = (PyObject *)((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
 
-    /* "pywrapfst.pyx":2321
+    /* "pywrapfst.pyx":2343
  *                      bool attach_new_isymbols=True,
  *                      _SymbolTable old_osymbols=None,
  *                      _SymbolTable new_osymbols=None,             # <<<<<<<<<<<<<<
@@ -26773,7 +25925,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables(PyObject *__
  *                      bool attach_new_osymbols=True):
  */
     values[5] = (PyObject *)((struct __pyx_obj_9pywrapfst__SymbolTable *)Py_None);
-    values[6] = ((PyObject *)__pyx_kp_b__24);
+    values[6] = ((PyObject *)__pyx_kp_b__10);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
@@ -26848,7 +26000,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables(PyObject *__
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "relabel_tables") < 0)) __PYX_ERR(0, 2315, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "relabel_tables") < 0)) __PYX_ERR(0, 2337, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -26876,10 +26028,10 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables(PyObject *__
     __pyx_v_new_isymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)values[1]);
     __pyx_v_unknown_isymbol = values[2];
     if (values[3]) {
-      __pyx_v_attach_new_isymbols = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_attach_new_isymbols == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2319, __pyx_L3_error)
+      __pyx_v_attach_new_isymbols = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_attach_new_isymbols == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2341, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":2319
+      /* "pywrapfst.pyx":2341
  *                      _SymbolTable new_isymbols=None,
  *                      unknown_isymbol=b"",
  *                      bool attach_new_isymbols=True,             # <<<<<<<<<<<<<<
@@ -26892,10 +26044,10 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables(PyObject *__
     __pyx_v_new_osymbols = ((struct __pyx_obj_9pywrapfst__SymbolTable *)values[5]);
     __pyx_v_unknown_osymbol = values[6];
     if (values[7]) {
-      __pyx_v_attach_new_osymbols = __Pyx_PyObject_IsTrue(values[7]); if (unlikely((__pyx_v_attach_new_osymbols == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2323, __pyx_L3_error)
+      __pyx_v_attach_new_osymbols = __Pyx_PyObject_IsTrue(values[7]); if (unlikely((__pyx_v_attach_new_osymbols == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2345, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":2323
+      /* "pywrapfst.pyx":2345
  *                      _SymbolTable new_osymbols=None,
  *                      unknown_osymbol=b"",
  *                      bool attach_new_osymbols=True):             # <<<<<<<<<<<<<<
@@ -26907,19 +26059,19 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables(PyObject *__
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("relabel_tables", 0, 0, 8, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2315, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("relabel_tables", 0, 0, 8, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2337, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.relabel_tables", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_old_isymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "old_isymbols", 0))) __PYX_ERR(0, 2316, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_new_isymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "new_isymbols", 0))) __PYX_ERR(0, 2317, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_old_osymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "old_osymbols", 0))) __PYX_ERR(0, 2320, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_new_osymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "new_osymbols", 0))) __PYX_ERR(0, 2321, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_old_isymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "old_isymbols", 0))) __PYX_ERR(0, 2338, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_new_isymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "new_isymbols", 0))) __PYX_ERR(0, 2339, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_old_osymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "old_osymbols", 0))) __PYX_ERR(0, 2342, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_new_osymbols), __pyx_ptype_9pywrapfst__SymbolTable, 1, "new_osymbols", 0))) __PYX_ERR(0, 2343, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_40relabel_tables(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), __pyx_v_old_isymbols, __pyx_v_new_isymbols, __pyx_v_unknown_isymbol, __pyx_v_attach_new_isymbols, __pyx_v_old_osymbols, __pyx_v_new_osymbols, __pyx_v_unknown_osymbol, __pyx_v_attach_new_osymbols);
 
-  /* "pywrapfst.pyx":2315
+  /* "pywrapfst.pyx":2337
  *     self._check_mutating_imethod()
  * 
  *   def relabel_tables(self,             # <<<<<<<<<<<<<<
@@ -26942,7 +26094,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_40relabel_tables(struct __pyx
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__relabel_tables __pyx_t_1;
   __Pyx_RefNannySetupContext("relabel_tables", 0);
 
-  /* "pywrapfst.pyx":2359
+  /* "pywrapfst.pyx":2381
  *     See also: `decode`, `encode`, `project`, `relabel_pairs`.
  *     """
  *     self._relabel_tables(old_isymbols, new_isymbols,             # <<<<<<<<<<<<<<
@@ -26951,10 +26103,10 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_40relabel_tables(struct __pyx
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_relabel_tables");
-    __PYX_ERR(0, 2359, __pyx_L1_error)
+    __PYX_ERR(0, 2381, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":2362
+  /* "pywrapfst.pyx":2384
  *                          unknown_isymbol, attach_new_isymbols,
  *                          old_osymbols, new_osymbols,
  *                          unknown_osymbol, attach_new_osymbols)             # <<<<<<<<<<<<<<
@@ -26970,9 +26122,9 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_40relabel_tables(struct __pyx
   __pyx_t_1.new_osymbols = __pyx_v_new_osymbols;
   __pyx_t_1.unknown_osymbol = __pyx_v_unknown_osymbol;
   __pyx_t_1.attach_new_osymbols = __pyx_v_attach_new_osymbols;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_relabel_tables(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2359, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_relabel_tables(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2381, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2363
+  /* "pywrapfst.pyx":2385
  *                          old_osymbols, new_osymbols,
  *                          unknown_osymbol, attach_new_osymbols)
  *     return self             # <<<<<<<<<<<<<<
@@ -26984,7 +26136,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_40relabel_tables(struct __pyx
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2315
+  /* "pywrapfst.pyx":2337
  *     self._check_mutating_imethod()
  * 
  *   def relabel_tables(self,             # <<<<<<<<<<<<<<
@@ -27002,7 +26154,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_40relabel_tables(struct __pyx
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2365
+/* "pywrapfst.pyx":2387
  *     return self
  * 
  *   cdef void _reserve_arcs(self, int64 state, size_t n) except *:             # <<<<<<<<<<<<<<
@@ -27015,9 +26167,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reserve_arcs(struct __pyx_obj_9pyw
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("_reserve_arcs", 0);
 
-  /* "pywrapfst.pyx":2366
+  /* "pywrapfst.pyx":2388
  * 
  *   cdef void _reserve_arcs(self, int64 state, size_t n) except *:
  *     if not self._mfst.get().ReserveArcs(state, n):             # <<<<<<<<<<<<<<
@@ -27026,28 +26179,40 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reserve_arcs(struct __pyx_obj_9pyw
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2366, __pyx_L1_error)
+    __PYX_ERR(0, 2388, __pyx_L1_error)
   }
   __pyx_t_1 = ((!(__pyx_v_self->_mfst.get()->ReserveArcs(__pyx_v_state, __pyx_v_n) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":2367
+    /* "pywrapfst.pyx":2389
  *   cdef void _reserve_arcs(self, int64 state, size_t n) except *:
  *     if not self._mfst.get().ReserveArcs(state, n):
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     self._check_mutating_imethod()
  * 
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2367, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__45, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2367, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2389, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2389, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 2367, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 2389, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2366
+    /* "pywrapfst.pyx":2388
  * 
  *   cdef void _reserve_arcs(self, int64 state, size_t n) except *:
  *     if not self._mfst.get().ReserveArcs(state, n):             # <<<<<<<<<<<<<<
@@ -27056,7 +26221,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reserve_arcs(struct __pyx_obj_9pyw
  */
   }
 
-  /* "pywrapfst.pyx":2368
+  /* "pywrapfst.pyx":2390
  *     if not self._mfst.get().ReserveArcs(state, n):
  *       raise FstIndexError("State index out of range")
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -27065,11 +26230,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reserve_arcs(struct __pyx_obj_9pyw
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2368, __pyx_L1_error)
+    __PYX_ERR(0, 2390, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2368, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2390, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2365
+  /* "pywrapfst.pyx":2387
  *     return self
  * 
  *   cdef void _reserve_arcs(self, int64 state, size_t n) except *:             # <<<<<<<<<<<<<<
@@ -27082,12 +26247,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reserve_arcs(struct __pyx_obj_9pyw
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst._MutableFst._reserve_arcs", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2370
+/* "pywrapfst.pyx":2392
  *     self._check_mutating_imethod()
  * 
  *   def reserve_arcs(self, int64 state, size_t n):             # <<<<<<<<<<<<<<
@@ -27127,11 +26293,11 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_43reserve_arcs(PyObject *__py
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_n)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("reserve_arcs", 1, 2, 2, 1); __PYX_ERR(0, 2370, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("reserve_arcs", 1, 2, 2, 1); __PYX_ERR(0, 2392, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "reserve_arcs") < 0)) __PYX_ERR(0, 2370, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "reserve_arcs") < 0)) __PYX_ERR(0, 2392, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -27139,12 +26305,12 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_43reserve_arcs(PyObject *__py
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2370, __pyx_L3_error)
-    __pyx_v_n = __Pyx_PyInt_As_size_t(values[1]); if (unlikely((__pyx_v_n == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 2370, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2392, __pyx_L3_error)
+    __pyx_v_n = __Pyx_PyInt_As_size_t(values[1]); if (unlikely((__pyx_v_n == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 2392, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("reserve_arcs", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2370, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("reserve_arcs", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2392, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.reserve_arcs", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -27162,7 +26328,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_42reserve_arcs(struct __pyx_o
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("reserve_arcs", 0);
 
-  /* "pywrapfst.pyx":2388
+  /* "pywrapfst.pyx":2410
  *     See also: `reserve_states`.
  *     """
  *     self._reserve_arcs(state, n)             # <<<<<<<<<<<<<<
@@ -27171,11 +26337,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_42reserve_arcs(struct __pyx_o
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reserve_arcs");
-    __PYX_ERR(0, 2388, __pyx_L1_error)
+    __PYX_ERR(0, 2410, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_reserve_arcs(__pyx_v_self, __pyx_v_state, __pyx_v_n); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2388, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_reserve_arcs(__pyx_v_self, __pyx_v_state, __pyx_v_n); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2410, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2389
+  /* "pywrapfst.pyx":2411
  *     """
  *     self._reserve_arcs(state, n)
  *     return self             # <<<<<<<<<<<<<<
@@ -27187,7 +26353,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_42reserve_arcs(struct __pyx_o
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2370
+  /* "pywrapfst.pyx":2392
  *     self._check_mutating_imethod()
  * 
  *   def reserve_arcs(self, int64 state, size_t n):             # <<<<<<<<<<<<<<
@@ -27205,7 +26371,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_42reserve_arcs(struct __pyx_o
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2391
+/* "pywrapfst.pyx":2413
  *     return self
  * 
  *   cdef void _reserve_states(self, int64 n) except *:             # <<<<<<<<<<<<<<
@@ -27217,7 +26383,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reserve_states(struct __pyx_obj_9p
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_reserve_states", 0);
 
-  /* "pywrapfst.pyx":2392
+  /* "pywrapfst.pyx":2414
  * 
  *   cdef void _reserve_states(self, int64 n) except *:
  *     self._mfst.get().ReserveStates(n)             # <<<<<<<<<<<<<<
@@ -27226,11 +26392,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reserve_states(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2392, __pyx_L1_error)
+    __PYX_ERR(0, 2414, __pyx_L1_error)
   }
   __pyx_v_self->_mfst.get()->ReserveStates(__pyx_v_n);
 
-  /* "pywrapfst.pyx":2393
+  /* "pywrapfst.pyx":2415
  *   cdef void _reserve_states(self, int64 n) except *:
  *     self._mfst.get().ReserveStates(n)
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -27239,11 +26405,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reserve_states(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2393, __pyx_L1_error)
+    __PYX_ERR(0, 2415, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2393, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2415, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2391
+  /* "pywrapfst.pyx":2413
  *     return self
  * 
  *   cdef void _reserve_states(self, int64 n) except *:             # <<<<<<<<<<<<<<
@@ -27259,7 +26425,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reserve_states(struct __pyx_obj_9p
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2395
+/* "pywrapfst.pyx":2417
  *     self._check_mutating_imethod()
  * 
  *   def reserve_states(self, int64 n):             # <<<<<<<<<<<<<<
@@ -27276,7 +26442,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_45reserve_states(PyObject *__
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("reserve_states (wrapper)", 0);
   assert(__pyx_arg_n); {
-    __pyx_v_n = __Pyx_PyInt_As_int64_t(__pyx_arg_n); if (unlikely((__pyx_v_n == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2395, __pyx_L3_error)
+    __pyx_v_n = __Pyx_PyInt_As_int64_t(__pyx_arg_n); if (unlikely((__pyx_v_n == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2417, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -27296,7 +26462,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_44reserve_states(struct __pyx
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("reserve_states", 0);
 
-  /* "pywrapfst.pyx":2409
+  /* "pywrapfst.pyx":2431
  *     See also: `reserve_arcs`.
  *     """
  *     self._reserve_states(n)             # <<<<<<<<<<<<<<
@@ -27305,11 +26471,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_44reserve_states(struct __pyx
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reserve_states");
-    __PYX_ERR(0, 2409, __pyx_L1_error)
+    __PYX_ERR(0, 2431, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_reserve_states(__pyx_v_self, __pyx_v_n); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2409, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_reserve_states(__pyx_v_self, __pyx_v_n); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2431, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2410
+  /* "pywrapfst.pyx":2432
  *     """
  *     self._reserve_states(n)
  *     return self             # <<<<<<<<<<<<<<
@@ -27321,7 +26487,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_44reserve_states(struct __pyx
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2395
+  /* "pywrapfst.pyx":2417
  *     self._check_mutating_imethod()
  * 
  *   def reserve_states(self, int64 n):             # <<<<<<<<<<<<<<
@@ -27339,7 +26505,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_44reserve_states(struct __pyx
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2412
+/* "pywrapfst.pyx":2434
  *     return self
  * 
  *   cdef void _reweight(self, potentials, bool to_final=False) except *:             # <<<<<<<<<<<<<<
@@ -27366,7 +26532,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
     }
   }
 
-  /* "pywrapfst.pyx":2414
+  /* "pywrapfst.pyx":2436
  *   cdef void _reweight(self, potentials, bool to_final=False) except *:
  *     cdef unique_ptr[vector[fst.WeightClass]] _potentials
  *     _potentials.reset(new vector[fst.WeightClass]())             # <<<<<<<<<<<<<<
@@ -27377,11 +26543,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
     __pyx_t_1 = new std::vector<fst::script::WeightClass> ();
   } catch(...) {
     __Pyx_CppExn2PyErr();
-    __PYX_ERR(0, 2414, __pyx_L1_error)
+    __PYX_ERR(0, 2436, __pyx_L1_error)
   }
   __pyx_v__potentials.reset(__pyx_t_1);
 
-  /* "pywrapfst.pyx":2415
+  /* "pywrapfst.pyx":2437
  *     cdef unique_ptr[vector[fst.WeightClass]] _potentials
  *     _potentials.reset(new vector[fst.WeightClass]())
  *     cdef string weight_type = self.weight_type()             # <<<<<<<<<<<<<<
@@ -27390,11 +26556,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-    __PYX_ERR(0, 2415, __pyx_L1_error)
+    __PYX_ERR(0, 2437, __pyx_L1_error)
   }
   __pyx_v_weight_type = ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.weight_type(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), 0);
 
-  /* "pywrapfst.pyx":2416
+  /* "pywrapfst.pyx":2438
  *     _potentials.reset(new vector[fst.WeightClass]())
  *     cdef string weight_type = self.weight_type()
  *     for weight in potentials:             # <<<<<<<<<<<<<<
@@ -27405,26 +26571,26 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
     __pyx_t_2 = __pyx_v_potentials; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
     __pyx_t_4 = NULL;
   } else {
-    __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_potentials); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2416, __pyx_L1_error)
+    __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_potentials); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2438, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2416, __pyx_L1_error)
+    __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2438, __pyx_L1_error)
   }
   for (;;) {
     if (likely(!__pyx_t_4)) {
       if (likely(PyList_CheckExact(__pyx_t_2))) {
         if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;
         #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_5 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 2416, __pyx_L1_error)
+        __pyx_t_5 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 2438, __pyx_L1_error)
         #else
-        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2416, __pyx_L1_error)
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2438, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_5);
         #endif
       } else {
         if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
         #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 2416, __pyx_L1_error)
+        __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 2438, __pyx_L1_error)
         #else
-        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2416, __pyx_L1_error)
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2438, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_5);
         #endif
       }
@@ -27434,7 +26600,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
         PyObject* exc_type = PyErr_Occurred();
         if (exc_type) {
           if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(0, 2416, __pyx_L1_error)
+          else __PYX_ERR(0, 2438, __pyx_L1_error)
         }
         break;
       }
@@ -27443,7 +26609,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
     __Pyx_XDECREF_SET(__pyx_v_weight, __pyx_t_5);
     __pyx_t_5 = 0;
 
-    /* "pywrapfst.pyx":2417
+    /* "pywrapfst.pyx":2439
  *     cdef string weight_type = self.weight_type()
  *     for weight in potentials:
  *         _potentials.get().push_back(_get_WeightClass_or_One(self.weight_type(),             # <<<<<<<<<<<<<<
@@ -27452,19 +26618,19 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
  */
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-      __PYX_ERR(0, 2417, __pyx_L1_error)
+      __PYX_ERR(0, 2439, __pyx_L1_error)
     }
 
-    /* "pywrapfst.pyx":2418
+    /* "pywrapfst.pyx":2440
  *     for weight in potentials:
  *         _potentials.get().push_back(_get_WeightClass_or_One(self.weight_type(),
  *                                                             weight))             # <<<<<<<<<<<<<<
  *     fst.Reweight(self._mfst.get(), deref(_potentials),
  *                  fst.GetReweightType(to_final))
  */
-    __pyx_t_6 = __pyx_f_9pywrapfst__get_WeightClass_or_One(((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.weight_type(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2417, __pyx_L1_error)
+    __pyx_t_6 = __pyx_f_9pywrapfst__get_WeightClass_or_One(((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.weight_type(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2439, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2417
+    /* "pywrapfst.pyx":2439
  *     cdef string weight_type = self.weight_type()
  *     for weight in potentials:
  *         _potentials.get().push_back(_get_WeightClass_or_One(self.weight_type(),             # <<<<<<<<<<<<<<
@@ -27475,10 +26641,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
       __pyx_v__potentials.get()->push_back(__pyx_t_6);
     } catch(...) {
       __Pyx_CppExn2PyErr();
-      __PYX_ERR(0, 2417, __pyx_L1_error)
+      __PYX_ERR(0, 2439, __pyx_L1_error)
     }
 
-    /* "pywrapfst.pyx":2416
+    /* "pywrapfst.pyx":2438
  *     _potentials.reset(new vector[fst.WeightClass]())
  *     cdef string weight_type = self.weight_type()
  *     for weight in potentials:             # <<<<<<<<<<<<<<
@@ -27488,7 +26654,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
   }
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":2419
+  /* "pywrapfst.pyx":2441
  *         _potentials.get().push_back(_get_WeightClass_or_One(self.weight_type(),
  *                                                             weight))
  *     fst.Reweight(self._mfst.get(), deref(_potentials),             # <<<<<<<<<<<<<<
@@ -27497,10 +26663,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2419, __pyx_L1_error)
+    __PYX_ERR(0, 2441, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":2420
+  /* "pywrapfst.pyx":2442
  *                                                             weight))
  *     fst.Reweight(self._mfst.get(), deref(_potentials),
  *                  fst.GetReweightType(to_final))             # <<<<<<<<<<<<<<
@@ -27509,7 +26675,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
  */
   fst::script::Reweight(__pyx_v_self->_mfst.get(), (*__pyx_v__potentials), fst::script::GetReweightType(__pyx_v_to_final));
 
-  /* "pywrapfst.pyx":2421
+  /* "pywrapfst.pyx":2443
  *     fst.Reweight(self._mfst.get(), deref(_potentials),
  *                  fst.GetReweightType(to_final))
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -27518,11 +26684,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2421, __pyx_L1_error)
+    __PYX_ERR(0, 2443, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2421, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2443, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2412
+  /* "pywrapfst.pyx":2434
  *     return self
  * 
  *   cdef void _reweight(self, potentials, bool to_final=False) except *:             # <<<<<<<<<<<<<<
@@ -27541,7 +26707,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__reweight(struct __pyx_obj_9pywrapf
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2423
+/* "pywrapfst.pyx":2445
  *     self._check_mutating_imethod()
  * 
  *   def reweight(self, potentials, bool to_final=False):             # <<<<<<<<<<<<<<
@@ -27585,7 +26751,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_47reweight(PyObject *__pyx_v_
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "reweight") < 0)) __PYX_ERR(0, 2423, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "reweight") < 0)) __PYX_ERR(0, 2445, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -27598,14 +26764,14 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_47reweight(PyObject *__pyx_v_
     }
     __pyx_v_potentials = values[0];
     if (values[1]) {
-      __pyx_v_to_final = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_to_final == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2423, __pyx_L3_error)
+      __pyx_v_to_final = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_to_final == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2445, __pyx_L3_error)
     } else {
       __pyx_v_to_final = ((bool)0);
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("reweight", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2423, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("reweight", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2445, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.reweight", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -27624,7 +26790,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_46reweight(struct __pyx_obj_9
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__reweight __pyx_t_1;
   __Pyx_RefNannySetupContext("reweight", 0);
 
-  /* "pywrapfst.pyx":2445
+  /* "pywrapfst.pyx":2467
  *       self.
  *     """
  *     self._reweight(potentials, to_final)             # <<<<<<<<<<<<<<
@@ -27633,13 +26799,13 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_46reweight(struct __pyx_obj_9
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reweight");
-    __PYX_ERR(0, 2445, __pyx_L1_error)
+    __PYX_ERR(0, 2467, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 1;
   __pyx_t_1.to_final = __pyx_v_to_final;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_reweight(__pyx_v_self, __pyx_v_potentials, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2445, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_reweight(__pyx_v_self, __pyx_v_potentials, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2467, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2446
+  /* "pywrapfst.pyx":2468
  *     """
  *     self._reweight(potentials, to_final)
  *     return self             # <<<<<<<<<<<<<<
@@ -27651,7 +26817,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_46reweight(struct __pyx_obj_9
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2423
+  /* "pywrapfst.pyx":2445
  *     self._check_mutating_imethod()
  * 
  *   def reweight(self, potentials, bool to_final=False):             # <<<<<<<<<<<<<<
@@ -27669,7 +26835,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_46reweight(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2448
+/* "pywrapfst.pyx":2470
  *     return self
  * 
  *   cdef void _rmepsilon(self,             # <<<<<<<<<<<<<<
@@ -27680,7 +26846,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_46reweight(struct __pyx_obj_9
 static void __pyx_f_9pywrapfst_11_MutableFst__rmepsilon(struct __pyx_obj_9pywrapfst__MutableFst *__pyx_v_self, struct __pyx_opt_args_9pywrapfst_11_MutableFst__rmepsilon *__pyx_optional_args) {
   PyObject *__pyx_v_queue_type = ((PyObject *)__pyx_n_b_auto);
 
-  /* "pywrapfst.pyx":2450
+  /* "pywrapfst.pyx":2472
  *   cdef void _rmepsilon(self,
  *                        queue_type=b"auto",
  *                        bool connect=True,             # <<<<<<<<<<<<<<
@@ -27689,7 +26855,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__rmepsilon(struct __pyx_obj_9pywrap
  */
   bool __pyx_v_connect = ((bool)1);
 
-  /* "pywrapfst.pyx":2451
+  /* "pywrapfst.pyx":2473
  *                        queue_type=b"auto",
  *                        bool connect=True,
  *                        weight=None,             # <<<<<<<<<<<<<<
@@ -27697,8 +26863,8 @@ static void __pyx_f_9pywrapfst_11_MutableFst__rmepsilon(struct __pyx_obj_9pywrap
  *                        float delta=fst.kShortestDelta) except *:
  */
   PyObject *__pyx_v_weight = ((PyObject *)Py_None);
-  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__46;
-  float __pyx_v_delta = __pyx_k__47;
+  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__19;
+  float __pyx_v_delta = __pyx_k__20;
   fst::script::WeightClass __pyx_v_wc;
   std::unique_ptr<fst::script::RmEpsilonOptions>  __pyx_v_opts;
   __Pyx_RefNannyDeclarations
@@ -27724,7 +26890,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__rmepsilon(struct __pyx_obj_9pywrap
     }
   }
 
-  /* "pywrapfst.pyx":2454
+  /* "pywrapfst.pyx":2476
  *                        int64 nstate=fst.kNoStateId,
  *                        float delta=fst.kShortestDelta) except *:
  *     cdef fst.WeightClass wc = _get_WeightClass_or_Zero(self.weight_type(),             # <<<<<<<<<<<<<<
@@ -27733,30 +26899,30 @@ static void __pyx_f_9pywrapfst_11_MutableFst__rmepsilon(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-    __PYX_ERR(0, 2454, __pyx_L1_error)
+    __PYX_ERR(0, 2476, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":2455
+  /* "pywrapfst.pyx":2477
  *                        float delta=fst.kShortestDelta) except *:
  *     cdef fst.WeightClass wc = _get_WeightClass_or_Zero(self.weight_type(),
  *                                                        weight)             # <<<<<<<<<<<<<<
  *     cdef unique_ptr[fst.RmEpsilonOptions] opts
  *     opts.reset(new fst.RmEpsilonOptions(_get_queue_type(tostring(queue_type)),
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.weight_type(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2454, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.weight_type(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2476, __pyx_L1_error)
   __pyx_v_wc = __pyx_t_1;
 
-  /* "pywrapfst.pyx":2457
+  /* "pywrapfst.pyx":2479
  *                                                        weight)
  *     cdef unique_ptr[fst.RmEpsilonOptions] opts
  *     opts.reset(new fst.RmEpsilonOptions(_get_queue_type(tostring(queue_type)),             # <<<<<<<<<<<<<<
  *                                         connect, wc, nstate, delta))
  *     fst.RmEpsilon(self._mfst.get(), deref(opts))
  */
-  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_queue_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2457, __pyx_L1_error)
-  __pyx_t_3 = __pyx_f_9pywrapfst__get_queue_type(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2457, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_queue_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2479, __pyx_L1_error)
+  __pyx_t_3 = __pyx_f_9pywrapfst__get_queue_type(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2479, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2458
+  /* "pywrapfst.pyx":2480
  *     cdef unique_ptr[fst.RmEpsilonOptions] opts
  *     opts.reset(new fst.RmEpsilonOptions(_get_queue_type(tostring(queue_type)),
  *                                         connect, wc, nstate, delta))             # <<<<<<<<<<<<<<
@@ -27765,7 +26931,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__rmepsilon(struct __pyx_obj_9pywrap
  */
   __pyx_v_opts.reset(new fst::script::RmEpsilonOptions(__pyx_t_3, __pyx_v_connect, __pyx_v_wc, __pyx_v_nstate, __pyx_v_delta));
 
-  /* "pywrapfst.pyx":2459
+  /* "pywrapfst.pyx":2481
  *     opts.reset(new fst.RmEpsilonOptions(_get_queue_type(tostring(queue_type)),
  *                                         connect, wc, nstate, delta))
  *     fst.RmEpsilon(self._mfst.get(), deref(opts))             # <<<<<<<<<<<<<<
@@ -27774,11 +26940,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__rmepsilon(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2459, __pyx_L1_error)
+    __PYX_ERR(0, 2481, __pyx_L1_error)
   }
   fst::script::RmEpsilon(__pyx_v_self->_mfst.get(), (*__pyx_v_opts));
 
-  /* "pywrapfst.pyx":2460
+  /* "pywrapfst.pyx":2482
  *                                         connect, wc, nstate, delta))
  *     fst.RmEpsilon(self._mfst.get(), deref(opts))
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -27787,11 +26953,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__rmepsilon(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2460, __pyx_L1_error)
+    __PYX_ERR(0, 2482, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2460, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2482, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2448
+  /* "pywrapfst.pyx":2470
  *     return self
  * 
  *   cdef void _rmepsilon(self,             # <<<<<<<<<<<<<<
@@ -27807,7 +26973,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__rmepsilon(struct __pyx_obj_9pywrap
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2462
+/* "pywrapfst.pyx":2484
  *     self._check_mutating_imethod()
  * 
  *   def rmepsilon(self,             # <<<<<<<<<<<<<<
@@ -27832,7 +26998,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_49rmepsilon(PyObject *__pyx_v
     PyObject* values[5] = {0,0,0,0,0};
     values[0] = ((PyObject *)__pyx_n_b_auto);
 
-    /* "pywrapfst.pyx":2465
+    /* "pywrapfst.pyx":2487
  *                 queue_type=b"auto",
  *                 bool connect=True,
  *                 weight=None,             # <<<<<<<<<<<<<<
@@ -27890,7 +27056,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_49rmepsilon(PyObject *__pyx_v
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "rmepsilon") < 0)) __PYX_ERR(0, 2462, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "rmepsilon") < 0)) __PYX_ERR(0, 2484, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -27910,10 +27076,10 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_49rmepsilon(PyObject *__pyx_v
     }
     __pyx_v_queue_type = values[0];
     if (values[1]) {
-      __pyx_v_connect = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_connect == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2464, __pyx_L3_error)
+      __pyx_v_connect = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_connect == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2486, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":2464
+      /* "pywrapfst.pyx":2486
  *   def rmepsilon(self,
  *                 queue_type=b"auto",
  *                 bool connect=True,             # <<<<<<<<<<<<<<
@@ -27924,19 +27090,19 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_49rmepsilon(PyObject *__pyx_v
     }
     __pyx_v_weight = values[2];
     if (values[3]) {
-      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2466, __pyx_L3_error)
+      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2488, __pyx_L3_error)
     } else {
-      __pyx_v_nstate = __pyx_k__48;
+      __pyx_v_nstate = __pyx_k__21;
     }
     if (values[4]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[4]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 2467, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[4]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 2489, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__49;
+      __pyx_v_delta = __pyx_k__22;
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("rmepsilon", 0, 0, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2462, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("rmepsilon", 0, 0, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2484, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.rmepsilon", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -27944,7 +27110,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_49rmepsilon(PyObject *__pyx_v
   __pyx_L4_argument_unpacking_done:;
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_48rmepsilon(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), __pyx_v_queue_type, __pyx_v_connect, __pyx_v_weight, __pyx_v_nstate, __pyx_v_delta);
 
-  /* "pywrapfst.pyx":2462
+  /* "pywrapfst.pyx":2484
  *     self._check_mutating_imethod()
  * 
  *   def rmepsilon(self,             # <<<<<<<<<<<<<<
@@ -27963,7 +27129,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_48rmepsilon(struct __pyx_obj_
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__rmepsilon __pyx_t_1;
   __Pyx_RefNannySetupContext("rmepsilon", 0);
 
-  /* "pywrapfst.pyx":2489
+  /* "pywrapfst.pyx":2511
  *       self.
  *     """
  *     self._rmepsilon(queue_type, connect, weight, nstate, delta)             # <<<<<<<<<<<<<<
@@ -27972,7 +27138,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_48rmepsilon(struct __pyx_obj_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_rmepsilon");
-    __PYX_ERR(0, 2489, __pyx_L1_error)
+    __PYX_ERR(0, 2511, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 5;
   __pyx_t_1.queue_type = __pyx_v_queue_type;
@@ -27980,9 +27146,9 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_48rmepsilon(struct __pyx_obj_
   __pyx_t_1.weight = __pyx_v_weight;
   __pyx_t_1.nstate = __pyx_v_nstate;
   __pyx_t_1.delta = __pyx_v_delta;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_rmepsilon(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2489, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_rmepsilon(__pyx_v_self, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2511, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2490
+  /* "pywrapfst.pyx":2512
  *     """
  *     self._rmepsilon(queue_type, connect, weight, nstate, delta)
  *     return self             # <<<<<<<<<<<<<<
@@ -27994,7 +27160,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_48rmepsilon(struct __pyx_obj_
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2462
+  /* "pywrapfst.pyx":2484
  *     self._check_mutating_imethod()
  * 
  *   def rmepsilon(self,             # <<<<<<<<<<<<<<
@@ -28012,7 +27178,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_48rmepsilon(struct __pyx_obj_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2492
+/* "pywrapfst.pyx":2514
  *     return self
  * 
  *   cdef void _set_final(self, int64 state, weight=None) except *:             # <<<<<<<<<<<<<<
@@ -28027,7 +27193,8 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_final(struct __pyx_obj_9pywrap
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  fst::script::WeightClass __pyx_t_4;
+  PyObject *__pyx_t_4 = NULL;
+  fst::script::WeightClass __pyx_t_5;
   __Pyx_RefNannySetupContext("_set_final", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -28035,7 +27202,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_final(struct __pyx_obj_9pywrap
     }
   }
 
-  /* "pywrapfst.pyx":2493
+  /* "pywrapfst.pyx":2515
  * 
  *   cdef void _set_final(self, int64 state, weight=None) except *:
  *     if not self._mfst.get().ValidStateId(state):             # <<<<<<<<<<<<<<
@@ -28044,28 +27211,40 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_final(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2493, __pyx_L1_error)
+    __PYX_ERR(0, 2515, __pyx_L1_error)
   }
   __pyx_t_1 = ((!(__pyx_v_self->_mfst.get()->ValidStateId(__pyx_v_state) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":2494
+    /* "pywrapfst.pyx":2516
  *   cdef void _set_final(self, int64 state, weight=None) except *:
  *     if not self._mfst.get().ValidStateId(state):
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     cdef fst.WeightClass wc = _get_WeightClass_or_One(self.weight_type(),
  *                                                       weight)
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2494, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__50, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2494, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2516, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2516, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 2494, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 2516, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2493
+    /* "pywrapfst.pyx":2515
  * 
  *   cdef void _set_final(self, int64 state, weight=None) except *:
  *     if not self._mfst.get().ValidStateId(state):             # <<<<<<<<<<<<<<
@@ -28074,7 +27253,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_final(struct __pyx_obj_9pywrap
  */
   }
 
-  /* "pywrapfst.pyx":2495
+  /* "pywrapfst.pyx":2517
  *     if not self._mfst.get().ValidStateId(state):
  *       raise FstIndexError("State index out of range")
  *     cdef fst.WeightClass wc = _get_WeightClass_or_One(self.weight_type(),             # <<<<<<<<<<<<<<
@@ -28083,20 +27262,20 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_final(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-    __PYX_ERR(0, 2495, __pyx_L1_error)
+    __PYX_ERR(0, 2517, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":2496
+  /* "pywrapfst.pyx":2518
  *       raise FstIndexError("State index out of range")
  *     cdef fst.WeightClass wc = _get_WeightClass_or_One(self.weight_type(),
  *                                                       weight)             # <<<<<<<<<<<<<<
  *     if not self._mfst.get().SetFinal(state, wc):
  *       raise FstOpError("Incompatible or invalid weight")
  */
-  __pyx_t_4 = __pyx_f_9pywrapfst__get_WeightClass_or_One(((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.weight_type(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2495, __pyx_L1_error)
-  __pyx_v_wc = __pyx_t_4;
+  __pyx_t_5 = __pyx_f_9pywrapfst__get_WeightClass_or_One(((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->__pyx_base.weight_type(((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_self), 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2517, __pyx_L1_error)
+  __pyx_v_wc = __pyx_t_5;
 
-  /* "pywrapfst.pyx":2497
+  /* "pywrapfst.pyx":2519
  *     cdef fst.WeightClass wc = _get_WeightClass_or_One(self.weight_type(),
  *                                                       weight)
  *     if not self._mfst.get().SetFinal(state, wc):             # <<<<<<<<<<<<<<
@@ -28105,28 +27284,40 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_final(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2497, __pyx_L1_error)
+    __PYX_ERR(0, 2519, __pyx_L1_error)
   }
   __pyx_t_1 = ((!(__pyx_v_self->_mfst.get()->SetFinal(__pyx_v_state, __pyx_v_wc) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":2498
+    /* "pywrapfst.pyx":2520
  *                                                       weight)
  *     if not self._mfst.get().SetFinal(state, wc):
  *       raise FstOpError("Incompatible or invalid weight")             # <<<<<<<<<<<<<<
  *     self._check_mutating_imethod()
  * 
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2498, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2520, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple__51, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2498, __pyx_L1_error)
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_Incompatible_or_invalid_weight) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_Incompatible_or_invalid_weight);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2520, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 2498, __pyx_L1_error)
+    __PYX_ERR(0, 2520, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2497
+    /* "pywrapfst.pyx":2519
  *     cdef fst.WeightClass wc = _get_WeightClass_or_One(self.weight_type(),
  *                                                       weight)
  *     if not self._mfst.get().SetFinal(state, wc):             # <<<<<<<<<<<<<<
@@ -28135,7 +27326,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_final(struct __pyx_obj_9pywrap
  */
   }
 
-  /* "pywrapfst.pyx":2499
+  /* "pywrapfst.pyx":2521
  *     if not self._mfst.get().SetFinal(state, wc):
  *       raise FstOpError("Incompatible or invalid weight")
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -28144,11 +27335,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_final(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2499, __pyx_L1_error)
+    __PYX_ERR(0, 2521, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2499, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2521, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2492
+  /* "pywrapfst.pyx":2514
  *     return self
  * 
  *   cdef void _set_final(self, int64 state, weight=None) except *:             # <<<<<<<<<<<<<<
@@ -28161,12 +27352,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_final(struct __pyx_obj_9pywrap
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst._MutableFst._set_final", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2501
+/* "pywrapfst.pyx":2523
  *     self._check_mutating_imethod()
  * 
  *   def set_final(self, int64 state, weight=None):             # <<<<<<<<<<<<<<
@@ -28211,7 +27403,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_51set_final(PyObject *__pyx_v
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_final") < 0)) __PYX_ERR(0, 2501, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_final") < 0)) __PYX_ERR(0, 2523, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -28222,12 +27414,12 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_51set_final(PyObject *__pyx_v
         default: goto __pyx_L5_argtuple_error;
       }
     }
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2501, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2523, __pyx_L3_error)
     __pyx_v_weight = values[1];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("set_final", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2501, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("set_final", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2523, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.set_final", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -28246,7 +27438,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_50set_final(struct __pyx_obj_
   struct __pyx_opt_args_9pywrapfst_11_MutableFst__set_final __pyx_t_1;
   __Pyx_RefNannySetupContext("set_final", 0);
 
-  /* "pywrapfst.pyx":2521
+  /* "pywrapfst.pyx":2543
  *     See also: `set_start`.
  *     """
  *     self._set_final(state, weight)             # <<<<<<<<<<<<<<
@@ -28255,13 +27447,13 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_50set_final(struct __pyx_obj_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_set_final");
-    __PYX_ERR(0, 2521, __pyx_L1_error)
+    __PYX_ERR(0, 2543, __pyx_L1_error)
   }
   __pyx_t_1.__pyx_n = 1;
   __pyx_t_1.weight = __pyx_v_weight;
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_set_final(__pyx_v_self, __pyx_v_state, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2521, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_set_final(__pyx_v_self, __pyx_v_state, &__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2543, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2522
+  /* "pywrapfst.pyx":2544
  *     """
  *     self._set_final(state, weight)
  *     return self             # <<<<<<<<<<<<<<
@@ -28273,7 +27465,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_50set_final(struct __pyx_obj_
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2501
+  /* "pywrapfst.pyx":2523
  *     self._check_mutating_imethod()
  * 
  *   def set_final(self, int64 state, weight=None):             # <<<<<<<<<<<<<<
@@ -28291,7 +27483,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_50set_final(struct __pyx_obj_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2524
+/* "pywrapfst.pyx":2546
  *     return self
  * 
  *   cdef void _set_input_symbols(self, _SymbolTable syms) except *:             # <<<<<<<<<<<<<<
@@ -28305,7 +27497,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_input_symbols(struct __pyx_obj
   int __pyx_t_2;
   __Pyx_RefNannySetupContext("_set_input_symbols", 0);
 
-  /* "pywrapfst.pyx":2525
+  /* "pywrapfst.pyx":2547
  * 
  *   cdef void _set_input_symbols(self, _SymbolTable syms) except *:
  *     if syms is None:             # <<<<<<<<<<<<<<
@@ -28316,7 +27508,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_input_symbols(struct __pyx_obj
   __pyx_t_2 = (__pyx_t_1 != 0);
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":2526
+    /* "pywrapfst.pyx":2548
  *   cdef void _set_input_symbols(self, _SymbolTable syms) except *:
  *     if syms is None:
  *       self._mfst.get().SetInputSymbols(NULL)             # <<<<<<<<<<<<<<
@@ -28325,11 +27517,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_input_symbols(struct __pyx_obj
  */
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-      __PYX_ERR(0, 2526, __pyx_L1_error)
+      __PYX_ERR(0, 2548, __pyx_L1_error)
     }
     __pyx_v_self->_mfst.get()->SetInputSymbols(NULL);
 
-    /* "pywrapfst.pyx":2527
+    /* "pywrapfst.pyx":2549
  *     if syms is None:
  *       self._mfst.get().SetInputSymbols(NULL)
  *       return             # <<<<<<<<<<<<<<
@@ -28338,7 +27530,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_input_symbols(struct __pyx_obj
  */
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":2525
+    /* "pywrapfst.pyx":2547
  * 
  *   cdef void _set_input_symbols(self, _SymbolTable syms) except *:
  *     if syms is None:             # <<<<<<<<<<<<<<
@@ -28347,7 +27539,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_input_symbols(struct __pyx_obj
  */
   }
 
-  /* "pywrapfst.pyx":2528
+  /* "pywrapfst.pyx":2550
  *       self._mfst.get().SetInputSymbols(NULL)
  *       return
  *     self._mfst.get().SetInputSymbols(syms._table)             # <<<<<<<<<<<<<<
@@ -28356,15 +27548,15 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_input_symbols(struct __pyx_obj
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2528, __pyx_L1_error)
+    __PYX_ERR(0, 2550, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_syms) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 2528, __pyx_L1_error)
+    __PYX_ERR(0, 2550, __pyx_L1_error)
   }
   __pyx_v_self->_mfst.get()->SetInputSymbols(__pyx_v_syms->_table);
 
-  /* "pywrapfst.pyx":2529
+  /* "pywrapfst.pyx":2551
  *       return
  *     self._mfst.get().SetInputSymbols(syms._table)
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -28373,11 +27565,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_input_symbols(struct __pyx_obj
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2529, __pyx_L1_error)
+    __PYX_ERR(0, 2551, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2529, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2551, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2524
+  /* "pywrapfst.pyx":2546
  *     return self
  * 
  *   cdef void _set_input_symbols(self, _SymbolTable syms) except *:             # <<<<<<<<<<<<<<
@@ -28393,7 +27585,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_input_symbols(struct __pyx_obj
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2531
+/* "pywrapfst.pyx":2553
  *     self._check_mutating_imethod()
  * 
  *   def set_input_symbols(self, _SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -28408,7 +27600,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_53set_input_symbols(PyObject
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_input_symbols (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 2531, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 2553, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_52set_input_symbols(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_syms));
 
   /* function exit code */
@@ -28425,7 +27617,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_52set_input_symbols(struct __
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_input_symbols", 0);
 
-  /* "pywrapfst.pyx":2547
+  /* "pywrapfst.pyx":2569
  *     See also: `set_output_symbols`.
  *     """
  *     self._set_input_symbols(syms)             # <<<<<<<<<<<<<<
@@ -28434,11 +27626,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_52set_input_symbols(struct __
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_set_input_symbols");
-    __PYX_ERR(0, 2547, __pyx_L1_error)
+    __PYX_ERR(0, 2569, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_set_input_symbols(__pyx_v_self, __pyx_v_syms); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2547, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_set_input_symbols(__pyx_v_self, __pyx_v_syms); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2569, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2548
+  /* "pywrapfst.pyx":2570
  *     """
  *     self._set_input_symbols(syms)
  *     return self             # <<<<<<<<<<<<<<
@@ -28450,7 +27642,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_52set_input_symbols(struct __
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2531
+  /* "pywrapfst.pyx":2553
  *     self._check_mutating_imethod()
  * 
  *   def set_input_symbols(self, _SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -28468,7 +27660,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_52set_input_symbols(struct __
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2550
+/* "pywrapfst.pyx":2572
  *     return self
  * 
  *   cdef void _set_output_symbols(self, _SymbolTable syms) except *:             # <<<<<<<<<<<<<<
@@ -28482,7 +27674,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_output_symbols(struct __pyx_ob
   int __pyx_t_2;
   __Pyx_RefNannySetupContext("_set_output_symbols", 0);
 
-  /* "pywrapfst.pyx":2551
+  /* "pywrapfst.pyx":2573
  * 
  *   cdef void _set_output_symbols(self, _SymbolTable syms) except *:
  *     if syms is None:             # <<<<<<<<<<<<<<
@@ -28493,7 +27685,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_output_symbols(struct __pyx_ob
   __pyx_t_2 = (__pyx_t_1 != 0);
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":2552
+    /* "pywrapfst.pyx":2574
  *   cdef void _set_output_symbols(self, _SymbolTable syms) except *:
  *     if syms is None:
  *       self._mfst.get().SetOutputSymbols(NULL)             # <<<<<<<<<<<<<<
@@ -28502,11 +27694,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_output_symbols(struct __pyx_ob
  */
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-      __PYX_ERR(0, 2552, __pyx_L1_error)
+      __PYX_ERR(0, 2574, __pyx_L1_error)
     }
     __pyx_v_self->_mfst.get()->SetOutputSymbols(NULL);
 
-    /* "pywrapfst.pyx":2553
+    /* "pywrapfst.pyx":2575
  *     if syms is None:
  *       self._mfst.get().SetOutputSymbols(NULL)
  *       return             # <<<<<<<<<<<<<<
@@ -28515,7 +27707,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_output_symbols(struct __pyx_ob
  */
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":2551
+    /* "pywrapfst.pyx":2573
  * 
  *   cdef void _set_output_symbols(self, _SymbolTable syms) except *:
  *     if syms is None:             # <<<<<<<<<<<<<<
@@ -28524,7 +27716,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_output_symbols(struct __pyx_ob
  */
   }
 
-  /* "pywrapfst.pyx":2554
+  /* "pywrapfst.pyx":2576
  *       self._mfst.get().SetOutputSymbols(NULL)
  *       return
  *     self._mfst.get().SetOutputSymbols(syms._table)             # <<<<<<<<<<<<<<
@@ -28533,15 +27725,15 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_output_symbols(struct __pyx_ob
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2554, __pyx_L1_error)
+    __PYX_ERR(0, 2576, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_syms) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-    __PYX_ERR(0, 2554, __pyx_L1_error)
+    __PYX_ERR(0, 2576, __pyx_L1_error)
   }
   __pyx_v_self->_mfst.get()->SetOutputSymbols(__pyx_v_syms->_table);
 
-  /* "pywrapfst.pyx":2555
+  /* "pywrapfst.pyx":2577
  *       return
  *     self._mfst.get().SetOutputSymbols(syms._table)
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -28550,11 +27742,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_output_symbols(struct __pyx_ob
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2555, __pyx_L1_error)
+    __PYX_ERR(0, 2577, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2555, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2577, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2550
+  /* "pywrapfst.pyx":2572
  *     return self
  * 
  *   cdef void _set_output_symbols(self, _SymbolTable syms) except *:             # <<<<<<<<<<<<<<
@@ -28570,7 +27762,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_output_symbols(struct __pyx_ob
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2557
+/* "pywrapfst.pyx":2579
  *     self._check_mutating_imethod()
  * 
  *   def set_output_symbols(self, _SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -28585,7 +27777,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_55set_output_symbols(PyObject
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_output_symbols (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 2557, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_syms), __pyx_ptype_9pywrapfst__SymbolTable, 1, "syms", 0))) __PYX_ERR(0, 2579, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_54set_output_symbols(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst__SymbolTable *)__pyx_v_syms));
 
   /* function exit code */
@@ -28602,7 +27794,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_54set_output_symbols(struct _
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_output_symbols", 0);
 
-  /* "pywrapfst.pyx":2573
+  /* "pywrapfst.pyx":2595
  *     See also: `set_input_symbols`.
  *     """
  *     self._set_output_symbols(syms)             # <<<<<<<<<<<<<<
@@ -28611,11 +27803,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_54set_output_symbols(struct _
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_set_output_symbols");
-    __PYX_ERR(0, 2573, __pyx_L1_error)
+    __PYX_ERR(0, 2595, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_set_output_symbols(__pyx_v_self, __pyx_v_syms); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2573, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_set_output_symbols(__pyx_v_self, __pyx_v_syms); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2595, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2574
+  /* "pywrapfst.pyx":2596
  *     """
  *     self._set_output_symbols(syms)
  *     return self             # <<<<<<<<<<<<<<
@@ -28627,7 +27819,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_54set_output_symbols(struct _
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2557
+  /* "pywrapfst.pyx":2579
  *     self._check_mutating_imethod()
  * 
  *   def set_output_symbols(self, _SymbolTable syms):             # <<<<<<<<<<<<<<
@@ -28645,7 +27837,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_54set_output_symbols(struct _
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2576
+/* "pywrapfst.pyx":2598
  *     return self
  * 
  *   cdef void _set_properties(self, uint64 props, uint64 mask):             # <<<<<<<<<<<<<<
@@ -28657,7 +27849,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_properties(struct __pyx_obj_9p
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_set_properties", 0);
 
-  /* "pywrapfst.pyx":2577
+  /* "pywrapfst.pyx":2599
  * 
  *   cdef void _set_properties(self, uint64 props, uint64 mask):
  *     self._mfst.get().SetProperties(props, mask)             # <<<<<<<<<<<<<<
@@ -28666,11 +27858,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_properties(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2577, __pyx_L1_error)
+    __PYX_ERR(0, 2599, __pyx_L1_error)
   }
   __pyx_v_self->_mfst.get()->SetProperties(__pyx_v_props, __pyx_v_mask);
 
-  /* "pywrapfst.pyx":2576
+  /* "pywrapfst.pyx":2598
  *     return self
  * 
  *   cdef void _set_properties(self, uint64 props, uint64 mask):             # <<<<<<<<<<<<<<
@@ -28686,7 +27878,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_properties(struct __pyx_obj_9p
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2579
+/* "pywrapfst.pyx":2601
  *     self._mfst.get().SetProperties(props, mask)
  * 
  *   def set_properties(self, uint64 props, uint64 mask):             # <<<<<<<<<<<<<<
@@ -28726,11 +27918,11 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_57set_properties(PyObject *__
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mask)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("set_properties", 1, 2, 2, 1); __PYX_ERR(0, 2579, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("set_properties", 1, 2, 2, 1); __PYX_ERR(0, 2601, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_properties") < 0)) __PYX_ERR(0, 2579, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_properties") < 0)) __PYX_ERR(0, 2601, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -28738,12 +27930,12 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_57set_properties(PyObject *__
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __pyx_v_props = __Pyx_PyInt_As_uint64_t(values[0]); if (unlikely((__pyx_v_props == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2579, __pyx_L3_error)
-    __pyx_v_mask = __Pyx_PyInt_As_uint64_t(values[1]); if (unlikely((__pyx_v_mask == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2579, __pyx_L3_error)
+    __pyx_v_props = __Pyx_PyInt_As_uint64_t(values[0]); if (unlikely((__pyx_v_props == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2601, __pyx_L3_error)
+    __pyx_v_mask = __Pyx_PyInt_As_uint64_t(values[1]); if (unlikely((__pyx_v_mask == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2601, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("set_properties", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2579, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("set_properties", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2601, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst._MutableFst.set_properties", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -28761,7 +27953,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_56set_properties(struct __pyx
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_properties", 0);
 
-  /* "pywrapfst.pyx":2593
+  /* "pywrapfst.pyx":2615
  *       self.
  *     """
  *     self._set_properties(props, mask)             # <<<<<<<<<<<<<<
@@ -28770,11 +27962,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_56set_properties(struct __pyx
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_set_properties");
-    __PYX_ERR(0, 2593, __pyx_L1_error)
+    __PYX_ERR(0, 2615, __pyx_L1_error)
   }
   ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_set_properties(__pyx_v_self, __pyx_v_props, __pyx_v_mask);
 
-  /* "pywrapfst.pyx":2594
+  /* "pywrapfst.pyx":2616
  *     """
  *     self._set_properties(props, mask)
  *     return self             # <<<<<<<<<<<<<<
@@ -28786,7 +27978,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_56set_properties(struct __pyx
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2579
+  /* "pywrapfst.pyx":2601
  *     self._mfst.get().SetProperties(props, mask)
  * 
  *   def set_properties(self, uint64 props, uint64 mask):             # <<<<<<<<<<<<<<
@@ -28804,7 +27996,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_56set_properties(struct __pyx
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2596
+/* "pywrapfst.pyx":2618
  *     return self
  * 
  *   cdef void _set_start(self, int64 state) except *:             # <<<<<<<<<<<<<<
@@ -28817,9 +28009,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_start(struct __pyx_obj_9pywrap
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("_set_start", 0);
 
-  /* "pywrapfst.pyx":2597
+  /* "pywrapfst.pyx":2619
  * 
  *   cdef void _set_start(self, int64 state) except *:
  *     if not self._mfst.get().SetStart(state):             # <<<<<<<<<<<<<<
@@ -28828,28 +28021,40 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_start(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2597, __pyx_L1_error)
+    __PYX_ERR(0, 2619, __pyx_L1_error)
   }
   __pyx_t_1 = ((!(__pyx_v_self->_mfst.get()->SetStart(__pyx_v_state) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":2598
+    /* "pywrapfst.pyx":2620
  *   cdef void _set_start(self, int64 state) except *:
  *     if not self._mfst.get().SetStart(state):
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     self._check_mutating_imethod()
  * 
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2598, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__52, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2598, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2620, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2620, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 2598, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 2620, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2597
+    /* "pywrapfst.pyx":2619
  * 
  *   cdef void _set_start(self, int64 state) except *:
  *     if not self._mfst.get().SetStart(state):             # <<<<<<<<<<<<<<
@@ -28858,7 +28063,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_start(struct __pyx_obj_9pywrap
  */
   }
 
-  /* "pywrapfst.pyx":2599
+  /* "pywrapfst.pyx":2621
  *     if not self._mfst.get().SetStart(state):
  *       raise FstIndexError("State index out of range")
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -28867,11 +28072,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_start(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2599, __pyx_L1_error)
+    __PYX_ERR(0, 2621, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2599, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2621, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2596
+  /* "pywrapfst.pyx":2618
  *     return self
  * 
  *   cdef void _set_start(self, int64 state) except *:             # <<<<<<<<<<<<<<
@@ -28884,12 +28089,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__set_start(struct __pyx_obj_9pywrap
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst._MutableFst._set_start", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2601
+/* "pywrapfst.pyx":2623
  *     self._check_mutating_imethod()
  * 
  *   def set_start(self, int64 state):             # <<<<<<<<<<<<<<
@@ -28906,7 +28112,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_59set_start(PyObject *__pyx_v
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_start (wrapper)", 0);
   assert(__pyx_arg_state); {
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2601, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(__pyx_arg_state); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2623, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -28926,7 +28132,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_58set_start(struct __pyx_obj_
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_start", 0);
 
-  /* "pywrapfst.pyx":2618
+  /* "pywrapfst.pyx":2640
  *     See also: `set_final`.
  *     """
  *     self._set_start(state)             # <<<<<<<<<<<<<<
@@ -28935,11 +28141,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_58set_start(struct __pyx_obj_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_set_start");
-    __PYX_ERR(0, 2618, __pyx_L1_error)
+    __PYX_ERR(0, 2640, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_set_start(__pyx_v_self, __pyx_v_state); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2618, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_set_start(__pyx_v_self, __pyx_v_state); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2640, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2619
+  /* "pywrapfst.pyx":2641
  *     """
  *     self._set_start(state)
  *     return self             # <<<<<<<<<<<<<<
@@ -28951,7 +28157,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_58set_start(struct __pyx_obj_
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2601
+  /* "pywrapfst.pyx":2623
  *     self._check_mutating_imethod()
  * 
  *   def set_start(self, int64 state):             # <<<<<<<<<<<<<<
@@ -28969,7 +28175,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_58set_start(struct __pyx_obj_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2621
+/* "pywrapfst.pyx":2643
  *     return self
  * 
  *   cdef void _topsort(self) except *:             # <<<<<<<<<<<<<<
@@ -28982,9 +28188,10 @@ static void __pyx_f_9pywrapfst_11_MutableFst__topsort(struct __pyx_obj_9pywrapfs
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("_topsort", 0);
 
-  /* "pywrapfst.pyx":2623
+  /* "pywrapfst.pyx":2645
  *   cdef void _topsort(self) except *:
  *     # TopSort returns False if the FST is cyclic, and thus can't be TopSorted.
  *     if not fst.TopSort(self._mfst.get()):             # <<<<<<<<<<<<<<
@@ -28993,29 +28200,41 @@ static void __pyx_f_9pywrapfst_11_MutableFst__topsort(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2623, __pyx_L1_error)
+    __PYX_ERR(0, 2645, __pyx_L1_error)
   }
   __pyx_t_1 = ((!(fst::script::TopSort(__pyx_v_self->_mfst.get()) != 0)) != 0);
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":2624
+    /* "pywrapfst.pyx":2646
  *     # TopSort returns False if the FST is cyclic, and thus can't be TopSorted.
  *     if not fst.TopSort(self._mfst.get()):
  *       logging.warning("Cannot topsort cyclic FST.")             # <<<<<<<<<<<<<<
  *     self._check_mutating_imethod()
  * 
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_logging); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2624, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_warning); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2624, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_logging); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2646, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple__53, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2624, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_warning); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2646, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_3 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_3)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_3, __pyx_kp_u_Cannot_topsort_cyclic_FST) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_u_Cannot_topsort_cyclic_FST);
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2646, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-    /* "pywrapfst.pyx":2623
+    /* "pywrapfst.pyx":2645
  *   cdef void _topsort(self) except *:
  *     # TopSort returns False if the FST is cyclic, and thus can't be TopSorted.
  *     if not fst.TopSort(self._mfst.get()):             # <<<<<<<<<<<<<<
@@ -29024,7 +28243,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__topsort(struct __pyx_obj_9pywrapfs
  */
   }
 
-  /* "pywrapfst.pyx":2625
+  /* "pywrapfst.pyx":2647
  *     if not fst.TopSort(self._mfst.get()):
  *       logging.warning("Cannot topsort cyclic FST.")
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -29033,11 +28252,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__topsort(struct __pyx_obj_9pywrapfs
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2625, __pyx_L1_error)
+    __PYX_ERR(0, 2647, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2625, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2647, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2621
+  /* "pywrapfst.pyx":2643
  *     return self
  * 
  *   cdef void _topsort(self) except *:             # <<<<<<<<<<<<<<
@@ -29050,12 +28269,13 @@ static void __pyx_f_9pywrapfst_11_MutableFst__topsort(struct __pyx_obj_9pywrapfs
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst._MutableFst._topsort", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2627
+/* "pywrapfst.pyx":2649
  *     self._check_mutating_imethod()
  * 
  *   def topsort(self):             # <<<<<<<<<<<<<<
@@ -29065,7 +28285,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__topsort(struct __pyx_obj_9pywrapfs
 
 /* Python wrapper */
 static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_61topsort(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9pywrapfst_11_MutableFst_60topsort[] = "\n    topsort(self)\n\n    Sorts transitions by state IDs.\n\n    This operation destructively topologically sorts the FST, if it is acyclic;\n    otherwise it remains unchanged. Once sorted, all transitions are from lower\n    state IDs to higher state IDs\n\n    Returns:\n       self.\n\n    See also: `arcsort`.\n    ";
+static char __pyx_doc_9pywrapfst_11_MutableFst_60topsort[] = "\n    topsort(self)\n\n    Sorts transitions by state IDs.\n\n    This operation destructively topologically sorts the FST, if it is acyclic;\n    otherwise it remains unchanged. Once sorted, all transitions are from lower\n    state IDs to higher state IDs\n\n    Returns:\n       self.\n    ";
 static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_61topsort(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
@@ -29082,8 +28302,8 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_60topsort(struct __pyx_obj_9p
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("topsort", 0);
 
-  /* "pywrapfst.pyx":2642
- *     See also: `arcsort`.
+  /* "pywrapfst.pyx":2662
+ *        self.
  *     """
  *     self._topsort()             # <<<<<<<<<<<<<<
  *     return self
@@ -29091,11 +28311,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_60topsort(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_topsort");
-    __PYX_ERR(0, 2642, __pyx_L1_error)
+    __PYX_ERR(0, 2662, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_topsort(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2642, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_topsort(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2662, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2643
+  /* "pywrapfst.pyx":2663
  *     """
  *     self._topsort()
  *     return self             # <<<<<<<<<<<<<<
@@ -29107,7 +28327,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_60topsort(struct __pyx_obj_9p
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2627
+  /* "pywrapfst.pyx":2649
  *     self._check_mutating_imethod()
  * 
  *   def topsort(self):             # <<<<<<<<<<<<<<
@@ -29125,7 +28345,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_60topsort(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2645
+/* "pywrapfst.pyx":2665
  *     return self
  * 
  *   cdef void _union(self, _Fst ifst) except *:             # <<<<<<<<<<<<<<
@@ -29137,7 +28357,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__union(struct __pyx_obj_9pywrapfst_
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_union", 0);
 
-  /* "pywrapfst.pyx":2646
+  /* "pywrapfst.pyx":2666
  * 
  *   cdef void _union(self, _Fst ifst) except *:
  *     fst.Union(self._mfst.get(), deref(ifst._fst))             # <<<<<<<<<<<<<<
@@ -29146,15 +28366,15 @@ static void __pyx_f_9pywrapfst_11_MutableFst__union(struct __pyx_obj_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2646, __pyx_L1_error)
+    __PYX_ERR(0, 2666, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 2646, __pyx_L1_error)
+    __PYX_ERR(0, 2666, __pyx_L1_error)
   }
   fst::script::Union(__pyx_v_self->_mfst.get(), (*__pyx_v_ifst->_fst));
 
-  /* "pywrapfst.pyx":2647
+  /* "pywrapfst.pyx":2667
  *   cdef void _union(self, _Fst ifst) except *:
  *     fst.Union(self._mfst.get(), deref(ifst._fst))
  *     self._check_mutating_imethod()             # <<<<<<<<<<<<<<
@@ -29163,11 +28383,11 @@ static void __pyx_f_9pywrapfst_11_MutableFst__union(struct __pyx_obj_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_check_mutating_imethod");
-    __PYX_ERR(0, 2647, __pyx_L1_error)
+    __PYX_ERR(0, 2667, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2647, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_check_mutating_imethod(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2667, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2645
+  /* "pywrapfst.pyx":2665
  *     return self
  * 
  *   cdef void _union(self, _Fst ifst) except *:             # <<<<<<<<<<<<<<
@@ -29183,7 +28403,7 @@ static void __pyx_f_9pywrapfst_11_MutableFst__union(struct __pyx_obj_9pywrapfst_
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":2649
+/* "pywrapfst.pyx":2669
  *     self._check_mutating_imethod()
  * 
  *   def union(self, _Fst ifst):             # <<<<<<<<<<<<<<
@@ -29198,7 +28418,7 @@ static PyObject *__pyx_pw_9pywrapfst_11_MutableFst_63union(PyObject *__pyx_v_sel
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("union (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 2649, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 2669, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_11_MutableFst_62union(((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_ifst));
 
   /* function exit code */
@@ -29215,7 +28435,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_62union(struct __pyx_obj_9pyw
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("union", 0);
 
-  /* "pywrapfst.pyx":2665
+  /* "pywrapfst.pyx":2685
  *       self.
  *     """
  *     self._union(ifst)             # <<<<<<<<<<<<<<
@@ -29224,11 +28444,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_62union(struct __pyx_obj_9pyw
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_union");
-    __PYX_ERR(0, 2665, __pyx_L1_error)
+    __PYX_ERR(0, 2685, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_union(__pyx_v_self, __pyx_v_ifst); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2665, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst__MutableFst *)__pyx_v_self->__pyx_base.__pyx_vtab)->_union(__pyx_v_self, __pyx_v_ifst); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2685, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2666
+  /* "pywrapfst.pyx":2686
  *     """
  *     self._union(ifst)
  *     return self             # <<<<<<<<<<<<<<
@@ -29240,7 +28460,7 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_62union(struct __pyx_obj_9pyw
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2649
+  /* "pywrapfst.pyx":2669
  *     self._check_mutating_imethod()
  * 
  *   def union(self, _Fst ifst):             # <<<<<<<<<<<<<<
@@ -29258,11 +28478,11 @@ static PyObject *__pyx_pf_9pywrapfst_11_MutableFst_62union(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2691
+/* "pywrapfst.pyx":2711
  * 
  * 
  * cdef _Fst _init_Fst(FstClass_ptr tfst):             # <<<<<<<<<<<<<<
- *   if tfst.Properties(fst.kError, True):
+ *   if tfst.Properties(fst.kError, True) == fst.kError:
  *     raise FstOpError("Operation failed")
  */
 
@@ -29273,56 +28493,69 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_Fst(__pyx_t_9p
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("_init_Fst", 0);
 
-  /* "pywrapfst.pyx":2692
+  /* "pywrapfst.pyx":2712
  * 
  * cdef _Fst _init_Fst(FstClass_ptr tfst):
- *   if tfst.Properties(fst.kError, True):             # <<<<<<<<<<<<<<
+ *   if tfst.Properties(fst.kError, True) == fst.kError:             # <<<<<<<<<<<<<<
  *     raise FstOpError("Operation failed")
  *   cdef _Fst ofst = _Fst.__new__(_Fst)
  */
-  __pyx_t_1 = (__pyx_v_tfst->Properties(fst::kError, 1) != 0);
+  __pyx_t_1 = ((__pyx_v_tfst->Properties(fst::kError, 1) == fst::kError) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":2693
+    /* "pywrapfst.pyx":2713
  * cdef _Fst _init_Fst(FstClass_ptr tfst):
- *   if tfst.Properties(fst.kError, True):
+ *   if tfst.Properties(fst.kError, True) == fst.kError:
  *     raise FstOpError("Operation failed")             # <<<<<<<<<<<<<<
  *   cdef _Fst ofst = _Fst.__new__(_Fst)
  *   ofst._fst.reset(tfst)
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2693, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__54, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2693, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2713, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_Operation_failed) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_Operation_failed);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2713, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 2693, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 2713, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2692
+    /* "pywrapfst.pyx":2712
  * 
  * cdef _Fst _init_Fst(FstClass_ptr tfst):
- *   if tfst.Properties(fst.kError, True):             # <<<<<<<<<<<<<<
+ *   if tfst.Properties(fst.kError, True) == fst.kError:             # <<<<<<<<<<<<<<
  *     raise FstOpError("Operation failed")
  *   cdef _Fst ofst = _Fst.__new__(_Fst)
  */
   }
 
-  /* "pywrapfst.pyx":2694
- *   if tfst.Properties(fst.kError, True):
+  /* "pywrapfst.pyx":2714
+ *   if tfst.Properties(fst.kError, True) == fst.kError:
  *     raise FstOpError("Operation failed")
  *   cdef _Fst ofst = _Fst.__new__(_Fst)             # <<<<<<<<<<<<<<
  *   ofst._fst.reset(tfst)
  *   return ofst
  */
-  __pyx_t_3 = ((PyObject *)__pyx_tp_new_9pywrapfst__Fst(((PyTypeObject *)__pyx_ptype_9pywrapfst__Fst), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2694, __pyx_L1_error)
-  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-  __pyx_v_ofst = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_3);
-  __pyx_t_3 = 0;
+  __pyx_t_2 = ((PyObject *)__pyx_tp_new_9pywrapfst__Fst(((PyTypeObject *)__pyx_ptype_9pywrapfst__Fst), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2714, __pyx_L1_error)
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_v_ofst = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
+  __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":2695
+  /* "pywrapfst.pyx":2715
  *     raise FstOpError("Operation failed")
  *   cdef _Fst ofst = _Fst.__new__(_Fst)
  *   ofst._fst.reset(tfst)             # <<<<<<<<<<<<<<
@@ -29331,11 +28564,11 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_Fst(__pyx_t_9p
  */
   if (unlikely(((PyObject *)__pyx_v_ofst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 2695, __pyx_L1_error)
+    __PYX_ERR(0, 2715, __pyx_L1_error)
   }
   __pyx_v_ofst->_fst.reset(__pyx_v_tfst);
 
-  /* "pywrapfst.pyx":2696
+  /* "pywrapfst.pyx":2716
  *   cdef _Fst ofst = _Fst.__new__(_Fst)
  *   ofst._fst.reset(tfst)
  *   return ofst             # <<<<<<<<<<<<<<
@@ -29347,11 +28580,11 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_Fst(__pyx_t_9p
   __pyx_r = __pyx_v_ofst;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2691
+  /* "pywrapfst.pyx":2711
  * 
  * 
  * cdef _Fst _init_Fst(FstClass_ptr tfst):             # <<<<<<<<<<<<<<
- *   if tfst.Properties(fst.kError, True):
+ *   if tfst.Properties(fst.kError, True) == fst.kError:
  *     raise FstOpError("Operation failed")
  */
 
@@ -29359,6 +28592,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_Fst(__pyx_t_9p
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst._init_Fst", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -29368,11 +28602,11 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_Fst(__pyx_t_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2699
+/* "pywrapfst.pyx":2719
  * 
  * 
  * cdef _MutableFst _init_MutableFst(MutableFstClass_ptr tfst):             # <<<<<<<<<<<<<<
- *   if tfst.Properties(fst.kError, True):
+ *   if tfst.Properties(fst.kError, True) == fst.kError:
  *     raise FstOpError("Operation failed")
  */
 
@@ -29383,56 +28617,69 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__init_Mutable
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("_init_MutableFst", 0);
 
-  /* "pywrapfst.pyx":2700
+  /* "pywrapfst.pyx":2720
  * 
  * cdef _MutableFst _init_MutableFst(MutableFstClass_ptr tfst):
- *   if tfst.Properties(fst.kError, True):             # <<<<<<<<<<<<<<
+ *   if tfst.Properties(fst.kError, True) == fst.kError:             # <<<<<<<<<<<<<<
  *     raise FstOpError("Operation failed")
  *   cdef _MutableFst ofst = _MutableFst.__new__(_MutableFst)
  */
-  __pyx_t_1 = (__pyx_v_tfst->Properties(fst::kError, 1) != 0);
+  __pyx_t_1 = ((__pyx_v_tfst->Properties(fst::kError, 1) == fst::kError) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":2701
+    /* "pywrapfst.pyx":2721
  * cdef _MutableFst _init_MutableFst(MutableFstClass_ptr tfst):
- *   if tfst.Properties(fst.kError, True):
+ *   if tfst.Properties(fst.kError, True) == fst.kError:
  *     raise FstOpError("Operation failed")             # <<<<<<<<<<<<<<
  *   cdef _MutableFst ofst = _MutableFst.__new__(_MutableFst)
  *   ofst._fst.reset(tfst)
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2701, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__55, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2701, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2721, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_Operation_failed) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_Operation_failed);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2721, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 2701, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 2721, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2700
+    /* "pywrapfst.pyx":2720
  * 
  * cdef _MutableFst _init_MutableFst(MutableFstClass_ptr tfst):
- *   if tfst.Properties(fst.kError, True):             # <<<<<<<<<<<<<<
+ *   if tfst.Properties(fst.kError, True) == fst.kError:             # <<<<<<<<<<<<<<
  *     raise FstOpError("Operation failed")
  *   cdef _MutableFst ofst = _MutableFst.__new__(_MutableFst)
  */
   }
 
-  /* "pywrapfst.pyx":2702
- *   if tfst.Properties(fst.kError, True):
+  /* "pywrapfst.pyx":2722
+ *   if tfst.Properties(fst.kError, True) == fst.kError:
  *     raise FstOpError("Operation failed")
  *   cdef _MutableFst ofst = _MutableFst.__new__(_MutableFst)             # <<<<<<<<<<<<<<
  *   ofst._fst.reset(tfst)
  *   # Makes a copy of it as the derived type! Cool.
  */
-  __pyx_t_3 = ((PyObject *)__pyx_tp_new_9pywrapfst__MutableFst(((PyTypeObject *)__pyx_ptype_9pywrapfst__MutableFst), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2702, __pyx_L1_error)
-  __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-  __pyx_v_ofst = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_3);
-  __pyx_t_3 = 0;
+  __pyx_t_2 = ((PyObject *)__pyx_tp_new_9pywrapfst__MutableFst(((PyTypeObject *)__pyx_ptype_9pywrapfst__MutableFst), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2722, __pyx_L1_error)
+  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+  __pyx_v_ofst = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_2);
+  __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":2703
+  /* "pywrapfst.pyx":2723
  *     raise FstOpError("Operation failed")
  *   cdef _MutableFst ofst = _MutableFst.__new__(_MutableFst)
  *   ofst._fst.reset(tfst)             # <<<<<<<<<<<<<<
@@ -29441,11 +28688,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__init_Mutable
  */
   if (unlikely(((PyObject *)__pyx_v_ofst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 2703, __pyx_L1_error)
+    __PYX_ERR(0, 2723, __pyx_L1_error)
   }
   __pyx_v_ofst->__pyx_base._fst.reset(__pyx_v_tfst);
 
-  /* "pywrapfst.pyx":2705
+  /* "pywrapfst.pyx":2725
  *   ofst._fst.reset(tfst)
  *   # Makes a copy of it as the derived type! Cool.
  *   ofst._mfst = static_pointer_cast[fst.MutableFstClass, fst.FstClass](ofst._fst)             # <<<<<<<<<<<<<<
@@ -29454,15 +28701,15 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__init_Mutable
  */
   if (unlikely(((PyObject *)__pyx_v_ofst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 2705, __pyx_L1_error)
+    __PYX_ERR(0, 2725, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ofst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 2705, __pyx_L1_error)
+    __PYX_ERR(0, 2725, __pyx_L1_error)
   }
   __pyx_v_ofst->_mfst = std::static_pointer_cast<fst::script::MutableFstClass,fst::script::FstClass>(__pyx_v_ofst->__pyx_base._fst);
 
-  /* "pywrapfst.pyx":2706
+  /* "pywrapfst.pyx":2726
  *   # Makes a copy of it as the derived type! Cool.
  *   ofst._mfst = static_pointer_cast[fst.MutableFstClass, fst.FstClass](ofst._fst)
  *   return ofst             # <<<<<<<<<<<<<<
@@ -29474,11 +28721,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__init_Mutable
   __pyx_r = __pyx_v_ofst;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2699
+  /* "pywrapfst.pyx":2719
  * 
  * 
  * cdef _MutableFst _init_MutableFst(MutableFstClass_ptr tfst):             # <<<<<<<<<<<<<<
- *   if tfst.Properties(fst.kError, True):
+ *   if tfst.Properties(fst.kError, True) == fst.kError:
  *     raise FstOpError("Operation failed")
  */
 
@@ -29486,6 +28733,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__init_Mutable
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst._init_MutableFst", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -29495,11 +28743,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__init_Mutable
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2709
+/* "pywrapfst.pyx":2729
  * 
  * 
  * cdef _Fst _init_XFst(FstClass_ptr tfst):             # <<<<<<<<<<<<<<
- *   if tfst.Properties(fst.kMutable, True):
+ *   if tfst.Properties(fst.kMutable, True) == fst.kMutable:
  *     return _init_MutableFst(static_cast[MutableFstClass_ptr](tfst))
  */
 
@@ -29510,40 +28758,40 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_XFst(__pyx_t_9
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("_init_XFst", 0);
 
-  /* "pywrapfst.pyx":2710
+  /* "pywrapfst.pyx":2730
  * 
  * cdef _Fst _init_XFst(FstClass_ptr tfst):
- *   if tfst.Properties(fst.kMutable, True):             # <<<<<<<<<<<<<<
+ *   if tfst.Properties(fst.kMutable, True) == fst.kMutable:             # <<<<<<<<<<<<<<
  *     return _init_MutableFst(static_cast[MutableFstClass_ptr](tfst))
  *   else:
  */
-  __pyx_t_1 = (__pyx_v_tfst->Properties(fst::kMutable, 1) != 0);
+  __pyx_t_1 = ((__pyx_v_tfst->Properties(fst::kMutable, 1) == fst::kMutable) != 0);
   if (__pyx_t_1) {
 
-    /* "pywrapfst.pyx":2711
+    /* "pywrapfst.pyx":2731
  * cdef _Fst _init_XFst(FstClass_ptr tfst):
- *   if tfst.Properties(fst.kMutable, True):
+ *   if tfst.Properties(fst.kMutable, True) == fst.kMutable:
  *     return _init_MutableFst(static_cast[MutableFstClass_ptr](tfst))             # <<<<<<<<<<<<<<
  *   else:
  *     return _init_Fst(tfst)
  */
     __Pyx_XDECREF(((PyObject *)__pyx_r));
-    __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(static_cast<__pyx_t_9pywrapfst_MutableFstClass_ptr>(__pyx_v_tfst))); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2711, __pyx_L1_error)
+    __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(static_cast<__pyx_t_9pywrapfst_MutableFstClass_ptr>(__pyx_v_tfst))); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2731, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
     __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
     __pyx_t_2 = 0;
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":2710
+    /* "pywrapfst.pyx":2730
  * 
  * cdef _Fst _init_XFst(FstClass_ptr tfst):
- *   if tfst.Properties(fst.kMutable, True):             # <<<<<<<<<<<<<<
+ *   if tfst.Properties(fst.kMutable, True) == fst.kMutable:             # <<<<<<<<<<<<<<
  *     return _init_MutableFst(static_cast[MutableFstClass_ptr](tfst))
  *   else:
  */
   }
 
-  /* "pywrapfst.pyx":2713
+  /* "pywrapfst.pyx":2733
  *     return _init_MutableFst(static_cast[MutableFstClass_ptr](tfst))
  *   else:
  *     return _init_Fst(tfst)             # <<<<<<<<<<<<<<
@@ -29552,18 +28800,18 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_XFst(__pyx_t_9
  */
   /*else*/ {
     __Pyx_XDECREF(((PyObject *)__pyx_r));
-    __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_Fst(__pyx_v_tfst)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2713, __pyx_L1_error)
+    __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_Fst(__pyx_v_tfst)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2733, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
     __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
     __pyx_t_2 = 0;
     goto __pyx_L0;
   }
 
-  /* "pywrapfst.pyx":2709
+  /* "pywrapfst.pyx":2729
  * 
  * 
  * cdef _Fst _init_XFst(FstClass_ptr tfst):             # <<<<<<<<<<<<<<
- *   if tfst.Properties(fst.kMutable, True):
+ *   if tfst.Properties(fst.kMutable, True) == fst.kMutable:
  *     return _init_MutableFst(static_cast[MutableFstClass_ptr](tfst))
  */
 
@@ -29578,7 +28826,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__init_XFst(__pyx_t_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2716
+/* "pywrapfst.pyx":2736
  * 
  * 
  * cdef _MutableFst _create_Fst(arc_type=b"standard"):             # <<<<<<<<<<<<<<
@@ -29598,7 +28846,6 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_create_Fst", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -29606,17 +28853,17 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
     }
   }
 
-  /* "pywrapfst.pyx":2718
+  /* "pywrapfst.pyx":2738
  * cdef _MutableFst _create_Fst(arc_type=b"standard"):
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(tostring(arc_type)))             # <<<<<<<<<<<<<<
  *   if tfst.get() == NULL:
  *     raise FstOpError("Unknown arc type: {!r}".format(arc_type))
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_arc_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2718, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_arc_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2738, __pyx_L1_error)
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(__pyx_t_1));
 
-  /* "pywrapfst.pyx":2719
+  /* "pywrapfst.pyx":2739
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(tostring(arc_type)))
  *   if tfst.get() == NULL:             # <<<<<<<<<<<<<<
@@ -29626,16 +28873,16 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
   __pyx_t_2 = ((__pyx_v_tfst.get() == NULL) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":2720
+    /* "pywrapfst.pyx":2740
  *   tfst.reset(new fst.VectorFstClass(tostring(arc_type)))
  *   if tfst.get() == NULL:
  *     raise FstOpError("Unknown arc type: {!r}".format(arc_type))             # <<<<<<<<<<<<<<
  *   return _init_MutableFst(tfst.release())
  * 
  */
-    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2720, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2740, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_arc_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2720, __pyx_L1_error)
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_arc_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2740, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
@@ -29647,38 +28894,10 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
         __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_arc_type); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2720, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_arc_type};
-        __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2720, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_arc_type};
-        __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2720, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2720, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_INCREF(__pyx_v_arc_type);
-        __Pyx_GIVEREF(__pyx_v_arc_type);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_arc_type);
-        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2720, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_v_arc_type) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_arc_type);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2740, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
@@ -29690,47 +28909,17 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
         __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2720, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2720, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2720, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2720, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_5);
-        __pyx_t_5 = 0;
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2720, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2740, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 2720, __pyx_L1_error)
+    __PYX_ERR(0, 2740, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2719
+    /* "pywrapfst.pyx":2739
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(tostring(arc_type)))
  *   if tfst.get() == NULL:             # <<<<<<<<<<<<<<
@@ -29739,7 +28928,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
  */
   }
 
-  /* "pywrapfst.pyx":2721
+  /* "pywrapfst.pyx":2741
  *   if tfst.get() == NULL:
  *     raise FstOpError("Unknown arc type: {!r}".format(arc_type))
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -29747,13 +28936,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2721, __pyx_L1_error)
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2741, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_3);
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2716
+  /* "pywrapfst.pyx":2736
  * 
  * 
  * cdef _MutableFst _create_Fst(arc_type=b"standard"):             # <<<<<<<<<<<<<<
@@ -29768,7 +28957,6 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._create_Fst", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -29777,7 +28965,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2724
+/* "pywrapfst.pyx":2744
  * 
  * 
  * cpdef _Fst _read(filename):             # <<<<<<<<<<<<<<
@@ -29785,7 +28973,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst__create_Fst(s
  *   tfst.reset(fst.FstClass.Read(tostring(filename)))
  */
 
-static PyObject *__pyx_pw_9pywrapfst_13_read(PyObject *__pyx_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_15_read(PyObject *__pyx_self, PyObject *__pyx_v_filename); /*proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *__pyx_v_filename, CYTHON_UNUSED int __pyx_skip_dispatch) {
   std::unique_ptr<fst::script::FstClass>  __pyx_v_tfst;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_r = NULL;
@@ -29797,20 +28985,19 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *__py
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("_read", 0);
 
-  /* "pywrapfst.pyx":2726
+  /* "pywrapfst.pyx":2746
  * cpdef _Fst _read(filename):
  *   cdef unique_ptr[fst.FstClass] tfst
  *   tfst.reset(fst.FstClass.Read(tostring(filename)))             # <<<<<<<<<<<<<<
  *   if tfst.get() == NULL:
  *     raise FstIOError("Read failed: {!r}".format(filename))
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2726, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2746, __pyx_L1_error)
   __pyx_v_tfst.reset(fst::script::FstClass::Read(__pyx_t_1));
 
-  /* "pywrapfst.pyx":2727
+  /* "pywrapfst.pyx":2747
  *   cdef unique_ptr[fst.FstClass] tfst
  *   tfst.reset(fst.FstClass.Read(tostring(filename)))
  *   if tfst.get() == NULL:             # <<<<<<<<<<<<<<
@@ -29820,16 +29007,16 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *__py
   __pyx_t_2 = ((__pyx_v_tfst.get() == NULL) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":2728
+    /* "pywrapfst.pyx":2748
  *   tfst.reset(fst.FstClass.Read(tostring(filename)))
  *   if tfst.get() == NULL:
  *     raise FstIOError("Read failed: {!r}".format(filename))             # <<<<<<<<<<<<<<
  *   return _init_XFst(tfst.release())
  * 
  */
-    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2728, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2748, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2728, __pyx_L1_error)
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2748, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
@@ -29841,38 +29028,10 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *__py
         __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_filename); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2728, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_filename};
-        __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2728, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_filename};
-        __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2728, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2728, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_INCREF(__pyx_v_filename);
-        __Pyx_GIVEREF(__pyx_v_filename);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_filename);
-        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2728, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_filename);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2748, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
@@ -29884,47 +29043,17 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *__py
         __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2728, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2728, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2728, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2728, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_5);
-        __pyx_t_5 = 0;
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2728, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2748, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 2728, __pyx_L1_error)
+    __PYX_ERR(0, 2748, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2727
+    /* "pywrapfst.pyx":2747
  *   cdef unique_ptr[fst.FstClass] tfst
  *   tfst.reset(fst.FstClass.Read(tostring(filename)))
  *   if tfst.get() == NULL:             # <<<<<<<<<<<<<<
@@ -29933,7 +29062,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *__py
  */
   }
 
-  /* "pywrapfst.pyx":2729
+  /* "pywrapfst.pyx":2749
  *   if tfst.get() == NULL:
  *     raise FstIOError("Read failed: {!r}".format(filename))
  *   return _init_XFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -29941,13 +29070,13 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *__py
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2729, __pyx_L1_error)
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2749, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_3);
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2724
+  /* "pywrapfst.pyx":2744
  * 
  * 
  * cpdef _Fst _read(filename):             # <<<<<<<<<<<<<<
@@ -29962,7 +29091,6 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *__py
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._read", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -29972,25 +29100,25 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read(PyObject *__py
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_13_read(PyObject *__pyx_self, PyObject *__pyx_v_filename); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_13_read(PyObject *__pyx_self, PyObject *__pyx_v_filename) {
+static PyObject *__pyx_pw_9pywrapfst_15_read(PyObject *__pyx_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_15_read(PyObject *__pyx_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_read (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_12_read(__pyx_self, ((PyObject *)__pyx_v_filename));
+  __pyx_r = __pyx_pf_9pywrapfst_14_read(__pyx_self, ((PyObject *)__pyx_v_filename));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_12_read(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_filename) {
+static PyObject *__pyx_pf_9pywrapfst_14_read(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("_read", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__read(__pyx_v_filename, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2724, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__read(__pyx_v_filename, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2744, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -30007,16 +29135,16 @@ static PyObject *__pyx_pf_9pywrapfst_12_read(CYTHON_UNUSED PyObject *__pyx_self,
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2732
+/* "pywrapfst.pyx":2752
  * 
  * 
- * cpdef _Fst _read_from_string(state):             # <<<<<<<<<<<<<<
+ * cpdef _Fst _read_Fst_from_string(state):             # <<<<<<<<<<<<<<
  *   cdef stringstream sstrm
  *   sstrm << tostring(state)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_15_read_from_string(PyObject *__pyx_self, PyObject *__pyx_v_state); /*proto*/
-static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read_from_string(PyObject *__pyx_v_state, CYTHON_UNUSED int __pyx_skip_dispatch) {
+static PyObject *__pyx_pw_9pywrapfst_17_read_Fst_from_string(PyObject *__pyx_self, PyObject *__pyx_v_state); /*proto*/
+static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read_Fst_from_string(PyObject *__pyx_v_state, CYTHON_UNUSED int __pyx_skip_dispatch) {
   std::stringstream __pyx_v_sstrm;
   std::unique_ptr<fst::script::FstClass>  __pyx_v_tfst;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_r = NULL;
@@ -30025,80 +29153,93 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read_from_string(Py
   int __pyx_t_2;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  __Pyx_RefNannySetupContext("_read_from_string", 0);
+  PyObject *__pyx_t_5 = NULL;
+  __Pyx_RefNannySetupContext("_read_Fst_from_string", 0);
 
-  /* "pywrapfst.pyx":2734
- * cpdef _Fst _read_from_string(state):
+  /* "pywrapfst.pyx":2754
+ * cpdef _Fst _read_Fst_from_string(state):
  *   cdef stringstream sstrm
  *   sstrm << tostring(state)             # <<<<<<<<<<<<<<
  *   cdef unique_ptr[fst.FstClass] tfst
- *   tfst.reset(fst.FstClass.ReadFromStream(sstrm, b"<pywrapfst>"))
+ *   tfst.reset(fst.FstClass.ReadStream(sstrm, b"<pywrapfst>"))
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_state, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2734, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_state, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2754, __pyx_L1_error)
   (void)((__pyx_v_sstrm << __pyx_t_1));
 
-  /* "pywrapfst.pyx":2736
+  /* "pywrapfst.pyx":2756
  *   sstrm << tostring(state)
  *   cdef unique_ptr[fst.FstClass] tfst
- *   tfst.reset(fst.FstClass.ReadFromStream(sstrm, b"<pywrapfst>"))             # <<<<<<<<<<<<<<
+ *   tfst.reset(fst.FstClass.ReadStream(sstrm, b"<pywrapfst>"))             # <<<<<<<<<<<<<<
  *   if tfst.get() == NULL:
- *     raise FstIOError("Read failed: <string>")
+ *     raise FstIOError("Read failed")
  */
   __pyx_v_tfst.reset(fst::script::FstClass::Read(__pyx_v_sstrm, __pyx_k_pywrapfst));
 
-  /* "pywrapfst.pyx":2737
+  /* "pywrapfst.pyx":2757
  *   cdef unique_ptr[fst.FstClass] tfst
- *   tfst.reset(fst.FstClass.ReadFromStream(sstrm, b"<pywrapfst>"))
+ *   tfst.reset(fst.FstClass.ReadStream(sstrm, b"<pywrapfst>"))
  *   if tfst.get() == NULL:             # <<<<<<<<<<<<<<
- *     raise FstIOError("Read failed: <string>")
+ *     raise FstIOError("Read failed")
  *   return _init_XFst(tfst.release())
  */
   __pyx_t_2 = ((__pyx_v_tfst.get() == NULL) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":2738
- *   tfst.reset(fst.FstClass.ReadFromStream(sstrm, b"<pywrapfst>"))
+    /* "pywrapfst.pyx":2758
+ *   tfst.reset(fst.FstClass.ReadStream(sstrm, b"<pywrapfst>"))
  *   if tfst.get() == NULL:
- *     raise FstIOError("Read failed: <string>")             # <<<<<<<<<<<<<<
+ *     raise FstIOError("Read failed")             # <<<<<<<<<<<<<<
  *   return _init_XFst(tfst.release())
  * 
  */
-    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2738, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple__56, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2738, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2758, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_u_Read_failed) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_u_Read_failed);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2758, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __PYX_ERR(0, 2738, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __PYX_ERR(0, 2758, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2737
+    /* "pywrapfst.pyx":2757
  *   cdef unique_ptr[fst.FstClass] tfst
- *   tfst.reset(fst.FstClass.ReadFromStream(sstrm, b"<pywrapfst>"))
+ *   tfst.reset(fst.FstClass.ReadStream(sstrm, b"<pywrapfst>"))
  *   if tfst.get() == NULL:             # <<<<<<<<<<<<<<
- *     raise FstIOError("Read failed: <string>")
+ *     raise FstIOError("Read failed")
  *   return _init_XFst(tfst.release())
  */
   }
 
-  /* "pywrapfst.pyx":2739
+  /* "pywrapfst.pyx":2759
  *   if tfst.get() == NULL:
- *     raise FstIOError("Read failed: <string>")
+ *     raise FstIOError("Read failed")
  *   return _init_XFst(tfst.release())             # <<<<<<<<<<<<<<
  * 
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_4 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2739, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_4);
-  __pyx_t_4 = 0;
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2759, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_3);
+  __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2732
+  /* "pywrapfst.pyx":2752
  * 
  * 
- * cpdef _Fst _read_from_string(state):             # <<<<<<<<<<<<<<
+ * cpdef _Fst _read_Fst_from_string(state):             # <<<<<<<<<<<<<<
  *   cdef stringstream sstrm
  *   sstrm << tostring(state)
  */
@@ -30107,7 +29248,8 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read_from_string(Py
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("pywrapfst._read_from_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("pywrapfst._read_Fst_from_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
   __Pyx_XGIVEREF((PyObject *)__pyx_r);
@@ -30116,25 +29258,25 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__read_from_string(Py
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_15_read_from_string(PyObject *__pyx_self, PyObject *__pyx_v_state); /*proto*/
-static PyObject *__pyx_pw_9pywrapfst_15_read_from_string(PyObject *__pyx_self, PyObject *__pyx_v_state) {
+static PyObject *__pyx_pw_9pywrapfst_17_read_Fst_from_string(PyObject *__pyx_self, PyObject *__pyx_v_state); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_17_read_Fst_from_string(PyObject *__pyx_self, PyObject *__pyx_v_state) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_read_from_string (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_14_read_from_string(__pyx_self, ((PyObject *)__pyx_v_state));
+  __Pyx_RefNannySetupContext("_read_Fst_from_string (wrapper)", 0);
+  __pyx_r = __pyx_pf_9pywrapfst_16_read_Fst_from_string(__pyx_self, ((PyObject *)__pyx_v_state));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_14_read_from_string(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_state) {
+static PyObject *__pyx_pf_9pywrapfst_16_read_Fst_from_string(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_state) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  __Pyx_RefNannySetupContext("_read_from_string", 0);
+  __Pyx_RefNannySetupContext("_read_Fst_from_string", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__read_from_string(__pyx_v_state, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2732, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__read_Fst_from_string(__pyx_v_state, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2752, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -30143,7 +29285,7 @@ static PyObject *__pyx_pf_9pywrapfst_14_read_from_string(CYTHON_UNUSED PyObject
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._read_from_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("pywrapfst._read_Fst_from_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
@@ -30151,7 +29293,7 @@ static PyObject *__pyx_pf_9pywrapfst_14_read_from_string(CYTHON_UNUSED PyObject
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2759
+/* "pywrapfst.pyx":2779
  *    """
  * 
  *    def __new__(cls, arc_type=b"standard"):             # <<<<<<<<<<<<<<
@@ -30161,7 +29303,7 @@ static PyObject *__pyx_pf_9pywrapfst_14_read_from_string(CYTHON_UNUSED PyObject
 
 /* Python wrapper */
 static PyObject *__pyx_pw_9pywrapfst_3Fst_1__new__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_9pywrapfst_3Fst_1__new__ = {"__new__", (PyCFunction)__pyx_pw_9pywrapfst_3Fst_1__new__, METH_VARARGS|METH_KEYWORDS, 0};
+static PyMethodDef __pyx_mdef_9pywrapfst_3Fst_1__new__ = {"__new__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_3Fst_1__new__, METH_VARARGS|METH_KEYWORDS, 0};
 static PyObject *__pyx_pw_9pywrapfst_3Fst_1__new__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   CYTHON_UNUSED PyObject *__pyx_v_cls = 0;
   PyObject *__pyx_v_arc_type = 0;
@@ -30196,7 +29338,7 @@ static PyObject *__pyx_pw_9pywrapfst_3Fst_1__new__(PyObject *__pyx_self, PyObjec
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__new__") < 0)) __PYX_ERR(0, 2759, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__new__") < 0)) __PYX_ERR(0, 2779, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -30212,7 +29354,7 @@ static PyObject *__pyx_pw_9pywrapfst_3Fst_1__new__(PyObject *__pyx_self, PyObjec
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__new__", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2759, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__new__", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2779, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.Fst.__new__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -30232,7 +29374,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Fst___new__(CYTHON_UNUSED PyObject *__pyx_
   struct __pyx_opt_args_9pywrapfst__create_Fst __pyx_t_2;
   __Pyx_RefNannySetupContext("__new__", 0);
 
-  /* "pywrapfst.pyx":2760
+  /* "pywrapfst.pyx":2780
  * 
  *    def __new__(cls, arc_type=b"standard"):
  *     return _create_Fst(arc_type)             # <<<<<<<<<<<<<<
@@ -30242,13 +29384,13 @@ static PyObject *__pyx_pf_9pywrapfst_3Fst___new__(CYTHON_UNUSED PyObject *__pyx_
   __Pyx_XDECREF(__pyx_r);
   __pyx_t_2.__pyx_n = 1;
   __pyx_t_2.arc_type = __pyx_v_arc_type;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__create_Fst(&__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2760, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__create_Fst(&__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2780, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2759
+  /* "pywrapfst.pyx":2779
  *    """
  * 
  *    def __new__(cls, arc_type=b"standard"):             # <<<<<<<<<<<<<<
@@ -30267,7 +29409,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Fst___new__(CYTHON_UNUSED PyObject *__pyx_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2763
+/* "pywrapfst.pyx":2783
  * 
  *    @staticmethod
  *    def read(filename):             # <<<<<<<<<<<<<<
@@ -30296,7 +29438,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Fst_2read(CYTHON_UNUSED PyObject *__pyx_se
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("read", 0);
 
-  /* "pywrapfst.pyx":2778
+  /* "pywrapfst.pyx":2798
  *        FstIOError: Read failed.
  *      """
  *      return _read(filename)             # <<<<<<<<<<<<<<
@@ -30304,13 +29446,13 @@ static PyObject *__pyx_pf_9pywrapfst_3Fst_2read(CYTHON_UNUSED PyObject *__pyx_se
  *    @staticmethod
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__read(__pyx_v_filename, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2778, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__read(__pyx_v_filename, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2798, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2763
+  /* "pywrapfst.pyx":2783
  * 
  *    @staticmethod
  *    def read(filename):             # <<<<<<<<<<<<<<
@@ -30329,7 +29471,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Fst_2read(CYTHON_UNUSED PyObject *__pyx_se
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2781
+/* "pywrapfst.pyx":2801
  * 
  *    @staticmethod
  *    def read_from_string(state):             # <<<<<<<<<<<<<<
@@ -30358,21 +29500,21 @@ static PyObject *__pyx_pf_9pywrapfst_3Fst_4read_from_string(CYTHON_UNUSED PyObje
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("read_from_string", 0);
 
-  /* "pywrapfst.pyx":2799
+  /* "pywrapfst.pyx":2819
  *      See also: `write_to_string`.
  *      """
- *      return _read_from_string(state)             # <<<<<<<<<<<<<<
+ *      return _read_Fst_from_string(state)             # <<<<<<<<<<<<<<
  * 
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__read_from_string(__pyx_v_state, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2799, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__read_Fst_from_string(__pyx_v_state, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2819, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2781
+  /* "pywrapfst.pyx":2801
  * 
  *    @staticmethod
  *    def read_from_string(state):             # <<<<<<<<<<<<<<
@@ -30391,7 +29533,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Fst_4read_from_string(CYTHON_UNUSED PyObje
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2914
+/* "pywrapfst.pyx":2932
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -30419,10 +29561,9 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc___repr__(struct __pyx_obj_9pywrapfst_A
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":2915
+  /* "pywrapfst.pyx":2933
  * 
  *   def __repr__(self):
  *     return "<Arc at 0x{:x}>".format(id(self))             # <<<<<<<<<<<<<<
@@ -30430,9 +29571,9 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc___repr__(struct __pyx_obj_9pywrapfst_A
  *   def __init__(self, int64 ilabel, int64 olabel, weight, int64 nextstate):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Arc_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2915, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Arc_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2933, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2915, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2933, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
@@ -30444,47 +29585,17 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc___repr__(struct __pyx_obj_9pywrapfst_A
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2915, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2915, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2915, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2915, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2915, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2933, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2914
+  /* "pywrapfst.pyx":2932
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -30498,7 +29609,6 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc___repr__(struct __pyx_obj_9pywrapfst_A
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst.Arc.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -30507,7 +29617,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc___repr__(struct __pyx_obj_9pywrapfst_A
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2917
+/* "pywrapfst.pyx":2935
  *     return "<Arc at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, int64 ilabel, int64 olabel, weight, int64 nextstate):             # <<<<<<<<<<<<<<
@@ -30552,23 +29662,23 @@ static int __pyx_pw_9pywrapfst_3Arc_3__init__(PyObject *__pyx_v_self, PyObject *
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_olabel)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("__init__", 1, 4, 4, 1); __PYX_ERR(0, 2917, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("__init__", 1, 4, 4, 1); __PYX_ERR(0, 2935, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
         if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_weight)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("__init__", 1, 4, 4, 2); __PYX_ERR(0, 2917, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("__init__", 1, 4, 4, 2); __PYX_ERR(0, 2935, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  3:
         if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_nextstate)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("__init__", 1, 4, 4, 3); __PYX_ERR(0, 2917, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("__init__", 1, 4, 4, 3); __PYX_ERR(0, 2935, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 2917, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 2935, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
       goto __pyx_L5_argtuple_error;
@@ -30578,14 +29688,14 @@ static int __pyx_pw_9pywrapfst_3Arc_3__init__(PyObject *__pyx_v_self, PyObject *
       values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
       values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
     }
-    __pyx_v_ilabel = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_ilabel == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2917, __pyx_L3_error)
-    __pyx_v_olabel = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_olabel == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2917, __pyx_L3_error)
+    __pyx_v_ilabel = __Pyx_PyInt_As_int64_t(values[0]); if (unlikely((__pyx_v_ilabel == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2935, __pyx_L3_error)
+    __pyx_v_olabel = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_olabel == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2935, __pyx_L3_error)
     __pyx_v_weight = values[2];
-    __pyx_v_nextstate = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_nextstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2917, __pyx_L3_error)
+    __pyx_v_nextstate = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_nextstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2935, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2917, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2935, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.Arc.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -30605,17 +29715,17 @@ static int __pyx_pf_9pywrapfst_3Arc_2__init__(struct __pyx_obj_9pywrapfst_Arc *_
   fst::script::WeightClass __pyx_t_1;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":2918
+  /* "pywrapfst.pyx":2936
  * 
  *   def __init__(self, int64 ilabel, int64 olabel, weight, int64 nextstate):
  *     cdef fst.WeightClass wc = _get_WeightClass_or_One(b"tropical", weight)             # <<<<<<<<<<<<<<
  *     self._arc.reset(new fst.ArcClass(ilabel, olabel, wc, nextstate))
  * 
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_One(__pyx_k_tropical, __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2918, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_One(__pyx_k_tropical, __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2936, __pyx_L1_error)
   __pyx_v_wc = __pyx_t_1;
 
-  /* "pywrapfst.pyx":2919
+  /* "pywrapfst.pyx":2937
  *   def __init__(self, int64 ilabel, int64 olabel, weight, int64 nextstate):
  *     cdef fst.WeightClass wc = _get_WeightClass_or_One(b"tropical", weight)
  *     self._arc.reset(new fst.ArcClass(ilabel, olabel, wc, nextstate))             # <<<<<<<<<<<<<<
@@ -30624,11 +29734,11 @@ static int __pyx_pf_9pywrapfst_3Arc_2__init__(struct __pyx_obj_9pywrapfst_Arc *_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 2919, __pyx_L1_error)
+    __PYX_ERR(0, 2937, __pyx_L1_error)
   }
   __pyx_v_self->_arc.reset(new fst::script::ArcClass(__pyx_v_ilabel, __pyx_v_olabel, __pyx_v_wc, __pyx_v_nextstate));
 
-  /* "pywrapfst.pyx":2917
+  /* "pywrapfst.pyx":2935
  *     return "<Arc at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, int64 ilabel, int64 olabel, weight, int64 nextstate):             # <<<<<<<<<<<<<<
@@ -30647,7 +29757,7 @@ static int __pyx_pf_9pywrapfst_3Arc_2__init__(struct __pyx_obj_9pywrapfst_Arc *_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2921
+/* "pywrapfst.pyx":2939
  *     self._arc.reset(new fst.ArcClass(ilabel, olabel, wc, nextstate))
  * 
  *   cpdef Arc copy(self):             # <<<<<<<<<<<<<<
@@ -30668,40 +29778,53 @@ static struct __pyx_obj_9pywrapfst_Arc *__pyx_f_9pywrapfst_3Arc_copy(struct __py
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_copy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2921, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_3Arc_5copy)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_copy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2939, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_3Arc_5copy)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2939, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_Arc))))) __PYX_ERR(0, 2939, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst_Arc *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2921, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2921, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst_Arc))))) __PYX_ERR(0, 2921, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst_Arc *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":2922
+  /* "pywrapfst.pyx":2940
  * 
  *   cpdef Arc copy(self):
  *     return Arc(self.ilabel, self.olabel, self.weight, self.nextstate)             # <<<<<<<<<<<<<<
@@ -30709,15 +29832,15 @@ static struct __pyx_obj_9pywrapfst_Arc *__pyx_f_9pywrapfst_3Arc_copy(struct __py
  *   property ilabel:
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_ilabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2922, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_ilabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2940, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_olabel); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2922, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_olabel); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2940, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_weight); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2922, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_weight); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2940, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_nextstate); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2922, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_nextstate); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2940, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = PyTuple_New(4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2922, __pyx_L1_error)
+  __pyx_t_5 = PyTuple_New(4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2940, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_5);
   __Pyx_GIVEREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1);
@@ -30731,14 +29854,14 @@ static struct __pyx_obj_9pywrapfst_Arc *__pyx_f_9pywrapfst_3Arc_copy(struct __py
   __pyx_t_2 = 0;
   __pyx_t_3 = 0;
   __pyx_t_4 = 0;
-  __pyx_t_4 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_Arc), __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2922, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_Arc), __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2940, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __pyx_r = ((struct __pyx_obj_9pywrapfst_Arc *)__pyx_t_4);
   __pyx_t_4 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2921
+  /* "pywrapfst.pyx":2939
  *     self._arc.reset(new fst.ArcClass(ilabel, olabel, wc, nextstate))
  * 
  *   cpdef Arc copy(self):             # <<<<<<<<<<<<<<
@@ -30780,7 +29903,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_4copy(struct __pyx_obj_9pywrapfst_Arc
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("copy", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_3Arc_copy(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2921, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_3Arc_copy(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2939, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -30797,7 +29920,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_4copy(struct __pyx_obj_9pywrapfst_Arc
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2926
+/* "pywrapfst.pyx":2944
  *   property ilabel:
  * 
  *     def __get__(self):             # <<<<<<<<<<<<<<
@@ -30824,7 +29947,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6ilabel___get__(struct __pyx_obj_9pywr
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__get__", 0);
 
-  /* "pywrapfst.pyx":2927
+  /* "pywrapfst.pyx":2945
  * 
  *     def __get__(self):
  *       return deref(self._arc).ilabel             # <<<<<<<<<<<<<<
@@ -30834,15 +29957,15 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6ilabel___get__(struct __pyx_obj_9pywr
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 2927, __pyx_L1_error)
+    __PYX_ERR(0, 2945, __pyx_L1_error)
   }
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t((*__pyx_v_self->_arc).ilabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2927, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t((*__pyx_v_self->_arc).ilabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2945, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2926
+  /* "pywrapfst.pyx":2944
  *   property ilabel:
  * 
  *     def __get__(self):             # <<<<<<<<<<<<<<
@@ -30861,7 +29984,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6ilabel___get__(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2929
+/* "pywrapfst.pyx":2947
  *       return deref(self._arc).ilabel
  * 
  *     def __set__(self, int64 value):             # <<<<<<<<<<<<<<
@@ -30877,7 +30000,7 @@ static int __pyx_pw_9pywrapfst_3Arc_6ilabel_3__set__(PyObject *__pyx_v_self, PyO
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
   assert(__pyx_arg_value); {
-    __pyx_v_value = __Pyx_PyInt_As_int64_t(__pyx_arg_value); if (unlikely((__pyx_v_value == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2929, __pyx_L3_error)
+    __pyx_v_value = __Pyx_PyInt_As_int64_t(__pyx_arg_value); if (unlikely((__pyx_v_value == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2947, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -30897,7 +30020,7 @@ static int __pyx_pf_9pywrapfst_3Arc_6ilabel_2__set__(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__", 0);
 
-  /* "pywrapfst.pyx":2930
+  /* "pywrapfst.pyx":2948
  * 
  *     def __set__(self, int64 value):
  *       deref(self._arc).ilabel = value             # <<<<<<<<<<<<<<
@@ -30906,11 +30029,11 @@ static int __pyx_pf_9pywrapfst_3Arc_6ilabel_2__set__(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 2930, __pyx_L1_error)
+    __PYX_ERR(0, 2948, __pyx_L1_error)
   }
   (*__pyx_v_self->_arc).ilabel = __pyx_v_value;
 
-  /* "pywrapfst.pyx":2929
+  /* "pywrapfst.pyx":2947
  *       return deref(self._arc).ilabel
  * 
  *     def __set__(self, int64 value):             # <<<<<<<<<<<<<<
@@ -30929,7 +30052,7 @@ static int __pyx_pf_9pywrapfst_3Arc_6ilabel_2__set__(struct __pyx_obj_9pywrapfst
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2934
+/* "pywrapfst.pyx":2952
  *   property olabel:
  * 
  *     def __get__(self):             # <<<<<<<<<<<<<<
@@ -30956,7 +30079,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6olabel___get__(struct __pyx_obj_9pywr
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__get__", 0);
 
-  /* "pywrapfst.pyx":2935
+  /* "pywrapfst.pyx":2953
  * 
  *     def __get__(self):
  *       return deref(self._arc).olabel             # <<<<<<<<<<<<<<
@@ -30966,15 +30089,15 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6olabel___get__(struct __pyx_obj_9pywr
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 2935, __pyx_L1_error)
+    __PYX_ERR(0, 2953, __pyx_L1_error)
   }
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t((*__pyx_v_self->_arc).olabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2935, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t((*__pyx_v_self->_arc).olabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2953, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2934
+  /* "pywrapfst.pyx":2952
  *   property olabel:
  * 
  *     def __get__(self):             # <<<<<<<<<<<<<<
@@ -30993,7 +30116,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6olabel___get__(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2937
+/* "pywrapfst.pyx":2955
  *       return deref(self._arc).olabel
  * 
  *     def __set__(self, int64 value):             # <<<<<<<<<<<<<<
@@ -31009,7 +30132,7 @@ static int __pyx_pw_9pywrapfst_3Arc_6olabel_3__set__(PyObject *__pyx_v_self, PyO
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
   assert(__pyx_arg_value); {
-    __pyx_v_value = __Pyx_PyInt_As_int64_t(__pyx_arg_value); if (unlikely((__pyx_v_value == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2937, __pyx_L3_error)
+    __pyx_v_value = __Pyx_PyInt_As_int64_t(__pyx_arg_value); if (unlikely((__pyx_v_value == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2955, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -31029,7 +30152,7 @@ static int __pyx_pf_9pywrapfst_3Arc_6olabel_2__set__(struct __pyx_obj_9pywrapfst
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__", 0);
 
-  /* "pywrapfst.pyx":2938
+  /* "pywrapfst.pyx":2956
  * 
  *     def __set__(self, int64 value):
  *       deref(self._arc).olabel = value             # <<<<<<<<<<<<<<
@@ -31038,11 +30161,11 @@ static int __pyx_pf_9pywrapfst_3Arc_6olabel_2__set__(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 2938, __pyx_L1_error)
+    __PYX_ERR(0, 2956, __pyx_L1_error)
   }
   (*__pyx_v_self->_arc).olabel = __pyx_v_value;
 
-  /* "pywrapfst.pyx":2937
+  /* "pywrapfst.pyx":2955
  *       return deref(self._arc).olabel
  * 
  *     def __set__(self, int64 value):             # <<<<<<<<<<<<<<
@@ -31061,7 +30184,7 @@ static int __pyx_pf_9pywrapfst_3Arc_6olabel_2__set__(struct __pyx_obj_9pywrapfst
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2942
+/* "pywrapfst.pyx":2960
  *   property weight:
  * 
  *     def __get__(self):             # <<<<<<<<<<<<<<
@@ -31089,19 +30212,19 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6weight___get__(struct __pyx_obj_9pywr
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__get__", 0);
 
-  /* "pywrapfst.pyx":2943
+  /* "pywrapfst.pyx":2961
  * 
  *     def __get__(self):
  *       cdef Weight weight = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *       weight._weight.reset(new fst.WeightClass(deref(self._arc).weight))
  *       return weight
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2943, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2961, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_weight = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2944
+  /* "pywrapfst.pyx":2962
  *     def __get__(self):
  *       cdef Weight weight = Weight.__new__(Weight)
  *       weight._weight.reset(new fst.WeightClass(deref(self._arc).weight))             # <<<<<<<<<<<<<<
@@ -31110,15 +30233,15 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6weight___get__(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_weight) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 2944, __pyx_L1_error)
+    __PYX_ERR(0, 2962, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 2944, __pyx_L1_error)
+    __PYX_ERR(0, 2962, __pyx_L1_error)
   }
   __pyx_v_weight->_weight.reset(new fst::script::WeightClass((*__pyx_v_self->_arc).weight));
 
-  /* "pywrapfst.pyx":2945
+  /* "pywrapfst.pyx":2963
  *       cdef Weight weight = Weight.__new__(Weight)
  *       weight._weight.reset(new fst.WeightClass(deref(self._arc).weight))
  *       return weight             # <<<<<<<<<<<<<<
@@ -31130,7 +30253,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6weight___get__(struct __pyx_obj_9pywr
   __pyx_r = ((PyObject *)__pyx_v_weight);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2942
+  /* "pywrapfst.pyx":2960
  *   property weight:
  * 
  *     def __get__(self):             # <<<<<<<<<<<<<<
@@ -31150,7 +30273,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6weight___get__(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2947
+/* "pywrapfst.pyx":2965
  *       return weight
  * 
  *     def __set__(self, weight):             # <<<<<<<<<<<<<<
@@ -31177,21 +30300,21 @@ static int __pyx_pf_9pywrapfst_3Arc_6weight_2__set__(struct __pyx_obj_9pywrapfst
   fst::script::WeightClass __pyx_t_1;
   __Pyx_RefNannySetupContext("__set__", 0);
 
-  /* "pywrapfst.pyx":2948
+  /* "pywrapfst.pyx":2966
  * 
  *     def __set__(self, weight):
  *       deref(self._arc).weight = _get_WeightClass_or_One(b"tropical", weight)             # <<<<<<<<<<<<<<
  * 
  *   property nextstate:
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_One(__pyx_k_tropical, __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2948, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_One(__pyx_k_tropical, __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 2966, __pyx_L1_error)
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 2948, __pyx_L1_error)
+    __PYX_ERR(0, 2966, __pyx_L1_error)
   }
   (*__pyx_v_self->_arc).weight = __pyx_t_1;
 
-  /* "pywrapfst.pyx":2947
+  /* "pywrapfst.pyx":2965
  *       return weight
  * 
  *     def __set__(self, weight):             # <<<<<<<<<<<<<<
@@ -31210,7 +30333,7 @@ static int __pyx_pf_9pywrapfst_3Arc_6weight_2__set__(struct __pyx_obj_9pywrapfst
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2952
+/* "pywrapfst.pyx":2970
  *   property nextstate:
  * 
  *     def __get__(self):             # <<<<<<<<<<<<<<
@@ -31237,7 +30360,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_9nextstate___get__(struct __pyx_obj_9p
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("__get__", 0);
 
-  /* "pywrapfst.pyx":2953
+  /* "pywrapfst.pyx":2971
  * 
  *     def __get__(self):
  *       return deref(self._arc).nextstate             # <<<<<<<<<<<<<<
@@ -31247,15 +30370,15 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_9nextstate___get__(struct __pyx_obj_9p
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 2953, __pyx_L1_error)
+    __PYX_ERR(0, 2971, __pyx_L1_error)
   }
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t((*__pyx_v_self->_arc).nextstate); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2953, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t((*__pyx_v_self->_arc).nextstate); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2971, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2952
+  /* "pywrapfst.pyx":2970
  *   property nextstate:
  * 
  *     def __get__(self):             # <<<<<<<<<<<<<<
@@ -31274,7 +30397,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_9nextstate___get__(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2955
+/* "pywrapfst.pyx":2973
  *       return deref(self._arc).nextstate
  * 
  *     def __set__(self, int64 value):             # <<<<<<<<<<<<<<
@@ -31290,7 +30413,7 @@ static int __pyx_pw_9pywrapfst_3Arc_9nextstate_3__set__(PyObject *__pyx_v_self,
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
   assert(__pyx_arg_value); {
-    __pyx_v_value = __Pyx_PyInt_As_int64_t(__pyx_arg_value); if (unlikely((__pyx_v_value == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2955, __pyx_L3_error)
+    __pyx_v_value = __Pyx_PyInt_As_int64_t(__pyx_arg_value); if (unlikely((__pyx_v_value == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2973, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -31310,7 +30433,7 @@ static int __pyx_pf_9pywrapfst_3Arc_9nextstate_2__set__(struct __pyx_obj_9pywrap
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__", 0);
 
-  /* "pywrapfst.pyx":2956
+  /* "pywrapfst.pyx":2974
  * 
  *     def __set__(self, int64 value):
  *       deref(self._arc).nextstate = value             # <<<<<<<<<<<<<<
@@ -31319,11 +30442,11 @@ static int __pyx_pf_9pywrapfst_3Arc_9nextstate_2__set__(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 2956, __pyx_L1_error)
+    __PYX_ERR(0, 2974, __pyx_L1_error)
   }
   (*__pyx_v_self->_arc).nextstate = __pyx_v_value;
 
-  /* "pywrapfst.pyx":2955
+  /* "pywrapfst.pyx":2973
  *       return deref(self._arc).nextstate
  * 
  *     def __set__(self, int64 value):             # <<<<<<<<<<<<<<
@@ -31373,7 +30496,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_6__reduce_cython__(CYTHON_UNUSED struc
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._arc cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__57, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__23, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -31426,7 +30549,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_8__setstate_cython__(CYTHON_UNUSED str
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._arc cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__58, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__24, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -31449,7 +30572,7 @@ static PyObject *__pyx_pf_9pywrapfst_3Arc_8__setstate_cython__(CYTHON_UNUSED str
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2959
+/* "pywrapfst.pyx":2977
  * 
  * 
  * cdef Arc _init_Arc(const fst.ArcClass &arc):             # <<<<<<<<<<<<<<
@@ -31467,19 +30590,19 @@ static struct __pyx_obj_9pywrapfst_Arc *__pyx_f_9pywrapfst__init_Arc(fst::script
   PyObject *__pyx_t_4 = NULL;
   __Pyx_RefNannySetupContext("_init_Arc", 0);
 
-  /* "pywrapfst.pyx":2960
+  /* "pywrapfst.pyx":2978
  * 
  * cdef Arc _init_Arc(const fst.ArcClass &arc):
  *   cdef Weight weight = Weight.__new__(Weight)             # <<<<<<<<<<<<<<
  *   weight._weight.reset(new fst.WeightClass(arc.weight))
  *   return Arc(arc.ilabel, arc.olabel, weight, arc.nextstate)
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2960, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_Weight(((PyTypeObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2978, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_weight = ((struct __pyx_obj_9pywrapfst_Weight *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2961
+  /* "pywrapfst.pyx":2979
  * cdef Arc _init_Arc(const fst.ArcClass &arc):
  *   cdef Weight weight = Weight.__new__(Weight)
  *   weight._weight.reset(new fst.WeightClass(arc.weight))             # <<<<<<<<<<<<<<
@@ -31488,11 +30611,11 @@ static struct __pyx_obj_9pywrapfst_Arc *__pyx_f_9pywrapfst__init_Arc(fst::script
  */
   if (unlikely(((PyObject *)__pyx_v_weight) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_weight");
-    __PYX_ERR(0, 2961, __pyx_L1_error)
+    __PYX_ERR(0, 2979, __pyx_L1_error)
   }
   __pyx_v_weight->_weight.reset(new fst::script::WeightClass(__pyx_v_arc.weight));
 
-  /* "pywrapfst.pyx":2962
+  /* "pywrapfst.pyx":2980
  *   cdef Weight weight = Weight.__new__(Weight)
  *   weight._weight.reset(new fst.WeightClass(arc.weight))
  *   return Arc(arc.ilabel, arc.olabel, weight, arc.nextstate)             # <<<<<<<<<<<<<<
@@ -31500,13 +30623,13 @@ static struct __pyx_obj_9pywrapfst_Arc *__pyx_f_9pywrapfst__init_Arc(fst::script
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_v_arc.ilabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2962, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_v_arc.ilabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2980, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_v_arc.olabel); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2962, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_v_arc.olabel); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2980, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_arc.nextstate); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2962, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyInt_From_int64_t(__pyx_v_arc.nextstate); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2980, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyTuple_New(4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2962, __pyx_L1_error)
+  __pyx_t_4 = PyTuple_New(4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2980, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
@@ -31520,14 +30643,14 @@ static struct __pyx_obj_9pywrapfst_Arc *__pyx_f_9pywrapfst__init_Arc(fst::script
   __pyx_t_1 = 0;
   __pyx_t_2 = 0;
   __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_Arc), __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2962, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_Arc), __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2980, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __pyx_r = ((struct __pyx_obj_9pywrapfst_Arc *)__pyx_t_3);
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2959
+  /* "pywrapfst.pyx":2977
  * 
  * 
  * cdef Arc _init_Arc(const fst.ArcClass &arc):             # <<<<<<<<<<<<<<
@@ -31550,7 +30673,7 @@ static struct __pyx_obj_9pywrapfst_Arc *__pyx_f_9pywrapfst__init_Arc(fst::script
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2973
+/* "pywrapfst.pyx":2991
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -31578,10 +30701,9 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator___repr__(struct __pyx_obj_9py
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":2974
+  /* "pywrapfst.pyx":2992
  * 
  *   def __repr__(self):
  *     return "<ArcIterator at 0x{:x}>".format(id(self))             # <<<<<<<<<<<<<<
@@ -31589,9 +30711,9 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator___repr__(struct __pyx_obj_9py
  *   def __init__(self, _Fst ifst, int64 state):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_ArcIterator_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2974, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_ArcIterator_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2992, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2974, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2992, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
@@ -31603,47 +30725,17 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator___repr__(struct __pyx_obj_9py
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2974, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2974, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2974, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2974, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2974, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2992, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2973
+  /* "pywrapfst.pyx":2991
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -31657,7 +30749,6 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator___repr__(struct __pyx_obj_9py
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst.ArcIterator.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -31666,7 +30757,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator___repr__(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2976
+/* "pywrapfst.pyx":2994
  *     return "<ArcIterator at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, _Fst ifst, int64 state):             # <<<<<<<<<<<<<<
@@ -31705,11 +30796,11 @@ static int __pyx_pw_9pywrapfst_11ArcIterator_3__init__(PyObject *__pyx_v_self, P
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_state)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 2976, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 2994, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 2976, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 2994, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -31718,17 +30809,17 @@ static int __pyx_pw_9pywrapfst_11ArcIterator_3__init__(PyObject *__pyx_v_self, P
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2976, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2994, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2976, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 2994, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.ArcIterator.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 2976, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 2994, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_11ArcIterator_2__init__(((struct __pyx_obj_9pywrapfst_ArcIterator *)__pyx_v_self), __pyx_v_ifst, __pyx_v_state);
 
   /* function exit code */
@@ -31746,10 +30837,11 @@ static int __pyx_pf_9pywrapfst_11ArcIterator_2__init__(struct __pyx_obj_9pywrapf
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  std::shared_ptr<fst::script::FstClass>  __pyx_t_4;
+  PyObject *__pyx_t_4 = NULL;
+  std::shared_ptr<fst::script::FstClass>  __pyx_t_5;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":2977
+  /* "pywrapfst.pyx":2995
  * 
  *   def __init__(self, _Fst ifst, int64 state):
  *     if not ifst._fst.get().ValidStateId(state):             # <<<<<<<<<<<<<<
@@ -31758,28 +30850,40 @@ static int __pyx_pf_9pywrapfst_11ArcIterator_2__init__(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 2977, __pyx_L1_error)
+    __PYX_ERR(0, 2995, __pyx_L1_error)
   }
   __pyx_t_1 = ((!(__pyx_v_ifst->_fst.get()->ValidStateId(__pyx_v_state) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":2978
+    /* "pywrapfst.pyx":2996
  *   def __init__(self, _Fst ifst, int64 state):
  *     if not ifst._fst.get().ValidStateId(state):
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
  *     self._fst = ifst._fst
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2978, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__59, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2978, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2996, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2996, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 2978, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 2996, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2977
+    /* "pywrapfst.pyx":2995
  * 
  *   def __init__(self, _Fst ifst, int64 state):
  *     if not ifst._fst.get().ValidStateId(state):             # <<<<<<<<<<<<<<
@@ -31788,7 +30892,7 @@ static int __pyx_pf_9pywrapfst_11ArcIterator_2__init__(struct __pyx_obj_9pywrapf
  */
   }
 
-  /* "pywrapfst.pyx":2980
+  /* "pywrapfst.pyx":2998
  *       raise FstIndexError("State index out of range")
  *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
  *     self._fst = ifst._fst             # <<<<<<<<<<<<<<
@@ -31797,16 +30901,16 @@ static int __pyx_pf_9pywrapfst_11ArcIterator_2__init__(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 2980, __pyx_L1_error)
+    __PYX_ERR(0, 2998, __pyx_L1_error)
   }
-  __pyx_t_4 = __pyx_v_ifst->_fst;
+  __pyx_t_5 = __pyx_v_ifst->_fst;
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 2980, __pyx_L1_error)
+    __PYX_ERR(0, 2998, __pyx_L1_error)
   }
-  __pyx_v_self->_fst = __pyx_t_4;
+  __pyx_v_self->_fst = __pyx_t_5;
 
-  /* "pywrapfst.pyx":2981
+  /* "pywrapfst.pyx":2999
  *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
  *     self._fst = ifst._fst
  *     self._aiter.reset(new fst.ArcIteratorClass(deref(self._fst), state))             # <<<<<<<<<<<<<<
@@ -31815,15 +30919,15 @@ static int __pyx_pf_9pywrapfst_11ArcIterator_2__init__(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 2981, __pyx_L1_error)
+    __PYX_ERR(0, 2999, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 2981, __pyx_L1_error)
+    __PYX_ERR(0, 2999, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.reset(new fst::script::ArcIteratorClass((*__pyx_v_self->_fst), __pyx_v_state));
 
-  /* "pywrapfst.pyx":2976
+  /* "pywrapfst.pyx":2994
  *     return "<ArcIterator at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, _Fst ifst, int64 state):             # <<<<<<<<<<<<<<
@@ -31837,6 +30941,7 @@ static int __pyx_pf_9pywrapfst_11ArcIterator_2__init__(struct __pyx_obj_9pywrapf
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst.ArcIterator.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = -1;
   __pyx_L0:;
@@ -31844,7 +30949,7 @@ static int __pyx_pf_9pywrapfst_11ArcIterator_2__init__(struct __pyx_obj_9pywrapf
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2984
+/* "pywrapfst.pyx":3002
  * 
  *   # This just registers this class as a possible iterator.
  *   def __iter__(self):             # <<<<<<<<<<<<<<
@@ -31870,7 +30975,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_4__iter__(struct __pyx_obj_9p
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__iter__", 0);
 
-  /* "pywrapfst.pyx":2985
+  /* "pywrapfst.pyx":3003
  *   # This just registers this class as a possible iterator.
  *   def __iter__(self):
  *     return self             # <<<<<<<<<<<<<<
@@ -31882,7 +30987,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_4__iter__(struct __pyx_obj_9p
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2984
+  /* "pywrapfst.pyx":3002
  * 
  *   # This just registers this class as a possible iterator.
  *   def __iter__(self):             # <<<<<<<<<<<<<<
@@ -31897,7 +31002,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_4__iter__(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2988
+/* "pywrapfst.pyx":3006
  * 
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):             # <<<<<<<<<<<<<<
@@ -31926,7 +31031,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_6__next__(struct __pyx_obj_9p
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("__next__", 0);
 
-  /* "pywrapfst.pyx":2989
+  /* "pywrapfst.pyx":3007
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):
  *     if self.done():             # <<<<<<<<<<<<<<
@@ -31935,12 +31040,12 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_6__next__(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "done");
-    __PYX_ERR(0, 2989, __pyx_L1_error)
+    __PYX_ERR(0, 3007, __pyx_L1_error)
   }
   __pyx_t_1 = (((struct __pyx_vtabstruct_9pywrapfst_ArcIterator *)__pyx_v_self->__pyx_vtab)->done(__pyx_v_self, 0) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":2990
+    /* "pywrapfst.pyx":3008
  *   def __next__(self):
  *     if self.done():
  *       raise StopIteration             # <<<<<<<<<<<<<<
@@ -31948,9 +31053,9 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_6__next__(struct __pyx_obj_9p
  *     self.next()
  */
     __Pyx_Raise(__pyx_builtin_StopIteration, 0, 0, 0);
-    __PYX_ERR(0, 2990, __pyx_L1_error)
+    __PYX_ERR(0, 3008, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":2989
+    /* "pywrapfst.pyx":3007
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):
  *     if self.done():             # <<<<<<<<<<<<<<
@@ -31959,7 +31064,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_6__next__(struct __pyx_obj_9p
  */
   }
 
-  /* "pywrapfst.pyx":2991
+  /* "pywrapfst.pyx":3009
  *     if self.done():
  *       raise StopIteration
  *     result = self.value()             # <<<<<<<<<<<<<<
@@ -31968,14 +31073,14 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_6__next__(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "value");
-    __PYX_ERR(0, 2991, __pyx_L1_error)
+    __PYX_ERR(0, 3009, __pyx_L1_error)
   }
-  __pyx_t_2 = ((struct __pyx_vtabstruct_9pywrapfst_ArcIterator *)__pyx_v_self->__pyx_vtab)->value(__pyx_v_self, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2991, __pyx_L1_error)
+  __pyx_t_2 = ((struct __pyx_vtabstruct_9pywrapfst_ArcIterator *)__pyx_v_self->__pyx_vtab)->value(__pyx_v_self, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3009, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_v_result = __pyx_t_2;
   __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":2992
+  /* "pywrapfst.pyx":3010
  *       raise StopIteration
  *     result = self.value()
  *     self.next()             # <<<<<<<<<<<<<<
@@ -31984,11 +31089,11 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_6__next__(struct __pyx_obj_9p
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "next");
-    __PYX_ERR(0, 2992, __pyx_L1_error)
+    __PYX_ERR(0, 3010, __pyx_L1_error)
   }
   ((struct __pyx_vtabstruct_9pywrapfst_ArcIterator *)__pyx_v_self->__pyx_vtab)->next(__pyx_v_self, 0);
 
-  /* "pywrapfst.pyx":2993
+  /* "pywrapfst.pyx":3011
  *     result = self.value()
  *     self.next()
  *     return result             # <<<<<<<<<<<<<<
@@ -32000,7 +31105,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_6__next__(struct __pyx_obj_9p
   __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2988
+  /* "pywrapfst.pyx":3006
  * 
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):             # <<<<<<<<<<<<<<
@@ -32020,7 +31125,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_6__next__(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":2995
+/* "pywrapfst.pyx":3013
  *     return result
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -32041,39 +31146,52 @@ static bool __pyx_f_9pywrapfst_11ArcIterator_done(struct __pyx_obj_9pywrapfst_Ar
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2995, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_9done)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3013, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11ArcIterator_9done)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3013, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3013, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2995, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2995, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 2995, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3004
+  /* "pywrapfst.pyx":3022
  *       True if the iterator is exhausted, False otherwise.
  *     """
  *     return self._aiter.get().Done()             # <<<<<<<<<<<<<<
@@ -32082,12 +31200,12 @@ static bool __pyx_f_9pywrapfst_11ArcIterator_done(struct __pyx_obj_9pywrapfst_Ar
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3004, __pyx_L1_error)
+    __PYX_ERR(0, 3022, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_aiter.get()->Done();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":2995
+  /* "pywrapfst.pyx":3013
  *     return result
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -32128,7 +31246,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_8done(struct __pyx_obj_9pywra
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("done", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_11ArcIterator_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2995, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_11ArcIterator_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3013, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -32145,7 +31263,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_8done(struct __pyx_obj_9pywra
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3006
+/* "pywrapfst.pyx":3024
  *     return self._aiter.get().Done()
  * 
  *   cpdef uint32 flags(self):             # <<<<<<<<<<<<<<
@@ -32166,39 +31284,52 @@ static __pyx_t_10basictypes_uint32 __pyx_f_9pywrapfst_11ArcIterator_flags(struct
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3006, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_11flags)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3024, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11ArcIterator_11flags)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3024, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_uint32_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3024, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3006, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3006, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_uint32_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3006, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3015
+  /* "pywrapfst.pyx":3033
  *       The current iterator behavioral flags as an integer.
  *     """
  *     return self._aiter.get().Flags()             # <<<<<<<<<<<<<<
@@ -32207,12 +31338,12 @@ static __pyx_t_10basictypes_uint32 __pyx_f_9pywrapfst_11ArcIterator_flags(struct
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3015, __pyx_L1_error)
+    __PYX_ERR(0, 3033, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_aiter.get()->Flags();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3006
+  /* "pywrapfst.pyx":3024
  *     return self._aiter.get().Done()
  * 
  *   cpdef uint32 flags(self):             # <<<<<<<<<<<<<<
@@ -32253,7 +31384,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_10flags(struct __pyx_obj_9pyw
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("flags", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(__pyx_f_9pywrapfst_11ArcIterator_flags(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3006, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(__pyx_f_9pywrapfst_11ArcIterator_flags(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3024, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -32270,7 +31401,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_10flags(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3017
+/* "pywrapfst.pyx":3035
  *     return self._aiter.get().Flags()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -32289,37 +31420,50 @@ static void __pyx_f_9pywrapfst_11ArcIterator_next(struct __pyx_obj_9pywrapfst_Ar
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3017, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_13next)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3035, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11ArcIterator_13next)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3035, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3017, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3017, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3023
+  /* "pywrapfst.pyx":3041
  *     Advances the iterator.
  *     """
  *     self._aiter.get().Next()             # <<<<<<<<<<<<<<
@@ -32328,11 +31472,11 @@ static void __pyx_f_9pywrapfst_11ArcIterator_next(struct __pyx_obj_9pywrapfst_Ar
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3023, __pyx_L1_error)
+    __PYX_ERR(0, 3041, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.get()->Next();
 
-  /* "pywrapfst.pyx":3017
+  /* "pywrapfst.pyx":3035
  *     return self._aiter.get().Flags()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -32372,7 +31516,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_12next(struct __pyx_obj_9pywr
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("next", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_11ArcIterator_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3017, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_11ArcIterator_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3035, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -32389,7 +31533,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_12next(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3025
+/* "pywrapfst.pyx":3043
  *     self._aiter.get().Next()
  * 
  *   cpdef size_t position(self):             # <<<<<<<<<<<<<<
@@ -32410,39 +31554,52 @@ static size_t __pyx_f_9pywrapfst_11ArcIterator_position(struct __pyx_obj_9pywrap
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_position); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3025, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_15position)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_position); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3043, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11ArcIterator_15position)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3043, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_5 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 3043, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3025, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3025, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_5 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 3025, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3034
+  /* "pywrapfst.pyx":3052
  *       The iterator's position, expressed as an integer.
  *     """
  *     return self._aiter.get().Position()             # <<<<<<<<<<<<<<
@@ -32451,12 +31608,12 @@ static size_t __pyx_f_9pywrapfst_11ArcIterator_position(struct __pyx_obj_9pywrap
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3034, __pyx_L1_error)
+    __PYX_ERR(0, 3052, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_aiter.get()->Position();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3025
+  /* "pywrapfst.pyx":3043
  *     self._aiter.get().Next()
  * 
  *   cpdef size_t position(self):             # <<<<<<<<<<<<<<
@@ -32497,7 +31654,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_14position(struct __pyx_obj_9
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("position", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_FromSize_t(__pyx_f_9pywrapfst_11ArcIterator_position(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3025, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_FromSize_t(__pyx_f_9pywrapfst_11ArcIterator_position(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3043, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -32514,7 +31671,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_14position(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3036
+/* "pywrapfst.pyx":3054
  *     return self._aiter.get().Position()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -32533,37 +31690,50 @@ static void __pyx_f_9pywrapfst_11ArcIterator_reset(struct __pyx_obj_9pywrapfst_A
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3036, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_17reset)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3054, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11ArcIterator_17reset)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3054, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3036, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3036, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3042
+  /* "pywrapfst.pyx":3060
  *     Resets the iterator to the initial position.
  *     """
  *     self._aiter.get().Reset()             # <<<<<<<<<<<<<<
@@ -32572,11 +31742,11 @@ static void __pyx_f_9pywrapfst_11ArcIterator_reset(struct __pyx_obj_9pywrapfst_A
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3042, __pyx_L1_error)
+    __PYX_ERR(0, 3060, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.get()->Reset();
 
-  /* "pywrapfst.pyx":3036
+  /* "pywrapfst.pyx":3054
  *     return self._aiter.get().Position()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -32616,7 +31786,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_16reset(struct __pyx_obj_9pyw
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("reset", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_11ArcIterator_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3036, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_11ArcIterator_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3054, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -32633,7 +31803,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_16reset(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3044
+/* "pywrapfst.pyx":3062
  *     self._aiter.get().Reset()
  * 
  *   cpdef void seek(self, size_t a):             # <<<<<<<<<<<<<<
@@ -32649,72 +31819,57 @@ static void __pyx_f_9pywrapfst_11ArcIterator_seek(struct __pyx_obj_9pywrapfst_Ar
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
   __Pyx_RefNannySetupContext("seek", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_seek); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3044, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_19seek)) {
-      __pyx_t_3 = __Pyx_PyInt_FromSize_t(__pyx_v_a); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3044, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_seek); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3062, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11ArcIterator_19seek)) {
+        __pyx_t_3 = __Pyx_PyInt_FromSize_t(__pyx_v_a); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3062, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3044, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3062, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3044, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3044, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3044, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3044, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3053
+  /* "pywrapfst.pyx":3071
  *       a: The position to seek to.
  *     """
  *     self._aiter.get().Seek(a)             # <<<<<<<<<<<<<<
@@ -32723,11 +31878,11 @@ static void __pyx_f_9pywrapfst_11ArcIterator_seek(struct __pyx_obj_9pywrapfst_Ar
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3053, __pyx_L1_error)
+    __PYX_ERR(0, 3071, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.get()->Seek(__pyx_v_a);
 
-  /* "pywrapfst.pyx":3044
+  /* "pywrapfst.pyx":3062
  *     self._aiter.get().Reset()
  * 
  *   cpdef void seek(self, size_t a):             # <<<<<<<<<<<<<<
@@ -32743,7 +31898,6 @@ static void __pyx_f_9pywrapfst_11ArcIterator_seek(struct __pyx_obj_9pywrapfst_Ar
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_WriteUnraisable("pywrapfst.ArcIterator.seek", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -32758,7 +31912,7 @@ static PyObject *__pyx_pw_9pywrapfst_11ArcIterator_19seek(PyObject *__pyx_v_self
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("seek (wrapper)", 0);
   assert(__pyx_arg_a); {
-    __pyx_v_a = __Pyx_PyInt_As_size_t(__pyx_arg_a); if (unlikely((__pyx_v_a == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 3044, __pyx_L3_error)
+    __pyx_v_a = __Pyx_PyInt_As_size_t(__pyx_arg_a); if (unlikely((__pyx_v_a == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 3062, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -32779,7 +31933,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_18seek(struct __pyx_obj_9pywr
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("seek", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_11ArcIterator_seek(__pyx_v_self, __pyx_v_a, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3044, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_11ArcIterator_seek(__pyx_v_self, __pyx_v_a, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3062, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -32796,7 +31950,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_18seek(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3055
+/* "pywrapfst.pyx":3073
  *     self._aiter.get().Seek(a)
  * 
  *   cpdef void set_flags(self, uint32 flags, uint32 mask):             # <<<<<<<<<<<<<<
@@ -32819,72 +31973,88 @@ static void __pyx_f_9pywrapfst_11ArcIterator_set_flags(struct __pyx_obj_9pywrapf
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3055, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_21set_flags)) {
-      __pyx_t_3 = __Pyx_PyInt_From_uint32_t(__pyx_v_flags); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3055, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = __Pyx_PyInt_From_uint32_t(__pyx_v_mask); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3055, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
-      __pyx_t_7 = 0;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
-        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
-        if (likely(__pyx_t_6)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-          __Pyx_INCREF(__pyx_t_6);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_5, function);
-          __pyx_t_7 = 1;
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3073, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11ArcIterator_21set_flags)) {
+        __pyx_t_3 = __Pyx_PyInt_From_uint32_t(__pyx_v_flags); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3073, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_4 = __Pyx_PyInt_From_uint32_t(__pyx_v_mask); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3073, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
+        __pyx_t_7 = 0;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
+          __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+          if (likely(__pyx_t_6)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+            __Pyx_INCREF(__pyx_t_6);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_5, function);
+            __pyx_t_7 = 1;
+          }
+        }
+        #if CYTHON_FAST_PYCALL
+        if (PyFunction_Check(__pyx_t_5)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
+          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3073, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        } else
+        #endif
+        #if CYTHON_FAST_PYCCALL
+        if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
+          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3073, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        } else
+        #endif
+        {
+          __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3073, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_8);
+          if (__pyx_t_6) {
+            __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
+          }
+          __Pyx_GIVEREF(__pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_3);
+          __Pyx_GIVEREF(__pyx_t_4);
+          PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_4);
+          __pyx_t_3 = 0;
+          __pyx_t_4 = 0;
+          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3073, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
         }
+        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3055, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3055, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3055, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        if (__pyx_t_6) {
-          __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        }
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_3);
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_4);
-        __pyx_t_3 = 0;
-        __pyx_t_4 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3055, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3065
+  /* "pywrapfst.pyx":3083
  *       mask: A mask to be applied to the `flags` argument before setting them.
  *     """
  *     self._aiter.get().SetFlags(flags, mask)             # <<<<<<<<<<<<<<
@@ -32893,11 +32063,11 @@ static void __pyx_f_9pywrapfst_11ArcIterator_set_flags(struct __pyx_obj_9pywrapf
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3065, __pyx_L1_error)
+    __PYX_ERR(0, 3083, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.get()->SetFlags(__pyx_v_flags, __pyx_v_mask);
 
-  /* "pywrapfst.pyx":3055
+  /* "pywrapfst.pyx":3073
  *     self._aiter.get().Seek(a)
  * 
  *   cpdef void set_flags(self, uint32 flags, uint32 mask):             # <<<<<<<<<<<<<<
@@ -32952,11 +32122,11 @@ static PyObject *__pyx_pw_9pywrapfst_11ArcIterator_21set_flags(PyObject *__pyx_v
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mask)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("set_flags", 1, 2, 2, 1); __PYX_ERR(0, 3055, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("set_flags", 1, 2, 2, 1); __PYX_ERR(0, 3073, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_flags") < 0)) __PYX_ERR(0, 3055, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_flags") < 0)) __PYX_ERR(0, 3073, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -32964,12 +32134,12 @@ static PyObject *__pyx_pw_9pywrapfst_11ArcIterator_21set_flags(PyObject *__pyx_v
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __pyx_v_flags = __Pyx_PyInt_As_uint32_t(values[0]); if (unlikely((__pyx_v_flags == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3055, __pyx_L3_error)
-    __pyx_v_mask = __Pyx_PyInt_As_uint32_t(values[1]); if (unlikely((__pyx_v_mask == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3055, __pyx_L3_error)
+    __pyx_v_flags = __Pyx_PyInt_As_uint32_t(values[0]); if (unlikely((__pyx_v_flags == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3073, __pyx_L3_error)
+    __pyx_v_mask = __Pyx_PyInt_As_uint32_t(values[1]); if (unlikely((__pyx_v_mask == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3073, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("set_flags", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3055, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("set_flags", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3073, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.ArcIterator.set_flags", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -32988,7 +32158,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_20set_flags(struct __pyx_obj_
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("set_flags", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_11ArcIterator_set_flags(__pyx_v_self, __pyx_v_flags, __pyx_v_mask, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3055, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_11ArcIterator_set_flags(__pyx_v_self, __pyx_v_flags, __pyx_v_mask, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3073, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -33005,7 +32175,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_20set_flags(struct __pyx_obj_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3067
+/* "pywrapfst.pyx":3085
  *     self._aiter.get().SetFlags(flags, mask)
  * 
  *   cpdef object value(self):             # <<<<<<<<<<<<<<
@@ -33025,39 +32195,52 @@ static PyObject *__pyx_f_9pywrapfst_11ArcIterator_value(struct __pyx_obj_9pywrap
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3067, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_23value)) {
-      __Pyx_XDECREF(__pyx_r);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3085, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_11ArcIterator_23value)) {
+        __Pyx_XDECREF(__pyx_r);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3085, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_r = __pyx_t_2;
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3067, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3067, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_r = __pyx_t_2;
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3073
+  /* "pywrapfst.pyx":3091
  *     Returns the current arc.
  *     """
  *     return _init_Arc(self._aiter.get().Value())             # <<<<<<<<<<<<<<
@@ -33067,15 +32250,15 @@ static PyObject *__pyx_f_9pywrapfst_11ArcIterator_value(struct __pyx_obj_9pywrap
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3073, __pyx_L1_error)
+    __PYX_ERR(0, 3091, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_Arc(__pyx_v_self->_aiter.get()->Value())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3073, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_Arc(__pyx_v_self->_aiter.get()->Value())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3091, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3067
+  /* "pywrapfst.pyx":3085
  *     self._aiter.get().SetFlags(flags, mask)
  * 
  *   cpdef object value(self):             # <<<<<<<<<<<<<<
@@ -33117,7 +32300,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_22value(struct __pyx_obj_9pyw
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("value", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_9pywrapfst_11ArcIterator_value(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3067, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_11ArcIterator_value(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3085, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -33165,7 +32348,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_24__reduce_cython__(CYTHON_UN
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._aiter,self._fst cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__60, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__25, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -33218,7 +32401,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_26__setstate_cython__(CYTHON_
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._aiter,self._fst cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__61, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__26, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -33241,7 +32424,7 @@ static PyObject *__pyx_pf_9pywrapfst_11ArcIterator_26__setstate_cython__(CYTHON_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3085
+/* "pywrapfst.pyx":3103
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -33269,10 +32452,9 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator___repr__(struct __pyx_
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":3086
+  /* "pywrapfst.pyx":3104
  * 
  *   def __repr__(self):
  *     return "<MutableArcIterator at 0x{:x}>".format(id(self))             # <<<<<<<<<<<<<<
@@ -33280,9 +32462,9 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator___repr__(struct __pyx_
  *   def __init__(self, _MutableFst ifst, int64 state):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_MutableArcIterator_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3086, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_MutableArcIterator_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3104, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3086, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3104, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
@@ -33294,47 +32476,17 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator___repr__(struct __pyx_
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3086, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3086, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3086, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3086, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3086, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3104, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3085
+  /* "pywrapfst.pyx":3103
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -33348,7 +32500,6 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator___repr__(struct __pyx_
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst.MutableArcIterator.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -33357,7 +32508,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator___repr__(struct __pyx_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3088
+/* "pywrapfst.pyx":3106
  *     return "<MutableArcIterator at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, _MutableFst ifst, int64 state):             # <<<<<<<<<<<<<<
@@ -33396,11 +32547,11 @@ static int __pyx_pw_9pywrapfst_18MutableArcIterator_3__init__(PyObject *__pyx_v_
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_state)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 3088, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 3106, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 3088, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 3106, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -33409,17 +32560,17 @@ static int __pyx_pw_9pywrapfst_18MutableArcIterator_3__init__(PyObject *__pyx_v_
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__MutableFst *)values[0]);
-    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3088, __pyx_L3_error)
+    __pyx_v_state = __Pyx_PyInt_As_int64_t(values[1]); if (unlikely((__pyx_v_state == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3106, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3088, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3106, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.MutableArcIterator.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__MutableFst, 1, "ifst", 0))) __PYX_ERR(0, 3088, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__MutableFst, 1, "ifst", 0))) __PYX_ERR(0, 3106, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_18MutableArcIterator_2__init__(((struct __pyx_obj_9pywrapfst_MutableArcIterator *)__pyx_v_self), __pyx_v_ifst, __pyx_v_state);
 
   /* function exit code */
@@ -33437,10 +32588,11 @@ static int __pyx_pf_9pywrapfst_18MutableArcIterator_2__init__(struct __pyx_obj_9
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  std::shared_ptr<fst::script::MutableFstClass>  __pyx_t_4;
+  PyObject *__pyx_t_4 = NULL;
+  std::shared_ptr<fst::script::MutableFstClass>  __pyx_t_5;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":3089
+  /* "pywrapfst.pyx":3107
  * 
  *   def __init__(self, _MutableFst ifst, int64 state):
  *     if not ifst._fst.get().ValidStateId(state):             # <<<<<<<<<<<<<<
@@ -33449,28 +32601,40 @@ static int __pyx_pf_9pywrapfst_18MutableArcIterator_2__init__(struct __pyx_obj_9
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3089, __pyx_L1_error)
+    __PYX_ERR(0, 3107, __pyx_L1_error)
   }
   __pyx_t_1 = ((!(__pyx_v_ifst->__pyx_base._fst.get()->ValidStateId(__pyx_v_state) != 0)) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":3090
+    /* "pywrapfst.pyx":3108
  *   def __init__(self, _MutableFst ifst, int64 state):
  *     if not ifst._fst.get().ValidStateId(state):
  *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
  *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
  *     self._mfst = ifst._mfst
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3090, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__62, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3090, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstIndexError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3108, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_u_State_index_out_of_range) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_u_State_index_out_of_range);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3108, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 3090, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 3108, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":3089
+    /* "pywrapfst.pyx":3107
  * 
  *   def __init__(self, _MutableFst ifst, int64 state):
  *     if not ifst._fst.get().ValidStateId(state):             # <<<<<<<<<<<<<<
@@ -33479,7 +32643,7 @@ static int __pyx_pf_9pywrapfst_18MutableArcIterator_2__init__(struct __pyx_obj_9
  */
   }
 
-  /* "pywrapfst.pyx":3092
+  /* "pywrapfst.pyx":3110
  *       raise FstIndexError("State index out of range")
  *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
  *     self._mfst = ifst._mfst             # <<<<<<<<<<<<<<
@@ -33488,16 +32652,16 @@ static int __pyx_pf_9pywrapfst_18MutableArcIterator_2__init__(struct __pyx_obj_9
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 3092, __pyx_L1_error)
+    __PYX_ERR(0, 3110, __pyx_L1_error)
   }
-  __pyx_t_4 = __pyx_v_ifst->_mfst;
+  __pyx_t_5 = __pyx_v_ifst->_mfst;
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 3092, __pyx_L1_error)
+    __PYX_ERR(0, 3110, __pyx_L1_error)
   }
-  __pyx_v_self->_mfst = __pyx_t_4;
+  __pyx_v_self->_mfst = __pyx_t_5;
 
-  /* "pywrapfst.pyx":3093
+  /* "pywrapfst.pyx":3111
  *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
  *     self._mfst = ifst._mfst
  *     self._aiter.reset(new fst.MutableArcIteratorClass(ifst._mfst.get(), state))             # <<<<<<<<<<<<<<
@@ -33506,15 +32670,15 @@ static int __pyx_pf_9pywrapfst_18MutableArcIterator_2__init__(struct __pyx_obj_9
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3093, __pyx_L1_error)
+    __PYX_ERR(0, 3111, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_mfst");
-    __PYX_ERR(0, 3093, __pyx_L1_error)
+    __PYX_ERR(0, 3111, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.reset(new fst::script::MutableArcIteratorClass(__pyx_v_ifst->_mfst.get(), __pyx_v_state));
 
-  /* "pywrapfst.pyx":3088
+  /* "pywrapfst.pyx":3106
  *     return "<MutableArcIterator at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, _MutableFst ifst, int64 state):             # <<<<<<<<<<<<<<
@@ -33528,6 +32692,7 @@ static int __pyx_pf_9pywrapfst_18MutableArcIterator_2__init__(struct __pyx_obj_9
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("pywrapfst.MutableArcIterator.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = -1;
   __pyx_L0:;
@@ -33535,7 +32700,7 @@ static int __pyx_pf_9pywrapfst_18MutableArcIterator_2__init__(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3095
+/* "pywrapfst.pyx":3113
  *     self._aiter.reset(new fst.MutableArcIteratorClass(ifst._mfst.get(), state))
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -33556,39 +32721,52 @@ static bool __pyx_f_9pywrapfst_18MutableArcIterator_done(struct __pyx_obj_9pywra
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3095, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_5done)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3113, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_18MutableArcIterator_5done)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3113, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3113, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3095, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3095, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3095, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3104
+  /* "pywrapfst.pyx":3122
  *       True if the iterator is exhausted, False otherwise.
  *     """
  *     return self._aiter.get().Done()             # <<<<<<<<<<<<<<
@@ -33597,12 +32775,12 @@ static bool __pyx_f_9pywrapfst_18MutableArcIterator_done(struct __pyx_obj_9pywra
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3104, __pyx_L1_error)
+    __PYX_ERR(0, 3122, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_aiter.get()->Done();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3095
+  /* "pywrapfst.pyx":3113
  *     self._aiter.reset(new fst.MutableArcIteratorClass(ifst._mfst.get(), state))
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -33643,7 +32821,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_4done(struct __pyx_obj
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("done", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_18MutableArcIterator_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3095, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_18MutableArcIterator_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3113, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -33660,7 +32838,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_4done(struct __pyx_obj
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3106
+/* "pywrapfst.pyx":3124
  *     return self._aiter.get().Done()
  * 
  *   cpdef uint32 flags(self):             # <<<<<<<<<<<<<<
@@ -33681,39 +32859,52 @@ static __pyx_t_10basictypes_uint32 __pyx_f_9pywrapfst_18MutableArcIterator_flags
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3106, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_7flags)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3124, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_18MutableArcIterator_7flags)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3124, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_uint32_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3124, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3106, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3106, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_uint32_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3106, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3115
+  /* "pywrapfst.pyx":3133
  *       The current iterator behavioral flags as an integer.
  *     """
  *     return self._aiter.get().Flags()             # <<<<<<<<<<<<<<
@@ -33722,12 +32913,12 @@ static __pyx_t_10basictypes_uint32 __pyx_f_9pywrapfst_18MutableArcIterator_flags
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3115, __pyx_L1_error)
+    __PYX_ERR(0, 3133, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_aiter.get()->Flags();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3106
+  /* "pywrapfst.pyx":3124
  *     return self._aiter.get().Done()
  * 
  *   cpdef uint32 flags(self):             # <<<<<<<<<<<<<<
@@ -33768,7 +32959,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_6flags(struct __pyx_ob
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("flags", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(__pyx_f_9pywrapfst_18MutableArcIterator_flags(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3106, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(__pyx_f_9pywrapfst_18MutableArcIterator_flags(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3124, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -33785,7 +32976,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_6flags(struct __pyx_ob
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3117
+/* "pywrapfst.pyx":3135
  *     return self._aiter.get().Flags()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -33804,37 +32995,50 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_next(struct __pyx_obj_9pywra
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3117, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_9next)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3135, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_18MutableArcIterator_9next)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3135, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3117, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3117, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3123
+  /* "pywrapfst.pyx":3141
  *     Advances the iterator.
  *     """
  *     self._aiter.get().Next()             # <<<<<<<<<<<<<<
@@ -33843,11 +33047,11 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_next(struct __pyx_obj_9pywra
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3123, __pyx_L1_error)
+    __PYX_ERR(0, 3141, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.get()->Next();
 
-  /* "pywrapfst.pyx":3117
+  /* "pywrapfst.pyx":3135
  *     return self._aiter.get().Flags()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -33887,7 +33091,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_8next(struct __pyx_obj
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("next", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3117, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3135, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -33904,7 +33108,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_8next(struct __pyx_obj
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3125
+/* "pywrapfst.pyx":3143
  *     self._aiter.get().Next()
  * 
  *   cpdef size_t position(self):             # <<<<<<<<<<<<<<
@@ -33925,39 +33129,52 @@ static size_t __pyx_f_9pywrapfst_18MutableArcIterator_position(struct __pyx_obj_
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_position); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3125, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_11position)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_position); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3143, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_18MutableArcIterator_11position)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3143, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_5 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 3143, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3125, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3125, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_size_t(__pyx_t_2); if (unlikely((__pyx_t_5 == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 3125, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3134
+  /* "pywrapfst.pyx":3152
  *       The iterator's position, expressed as an integer.
  *     """
  *     return self._aiter.get().Position()             # <<<<<<<<<<<<<<
@@ -33966,12 +33183,12 @@ static size_t __pyx_f_9pywrapfst_18MutableArcIterator_position(struct __pyx_obj_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3134, __pyx_L1_error)
+    __PYX_ERR(0, 3152, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_aiter.get()->Position();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3125
+  /* "pywrapfst.pyx":3143
  *     self._aiter.get().Next()
  * 
  *   cpdef size_t position(self):             # <<<<<<<<<<<<<<
@@ -34012,7 +33229,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_10position(struct __py
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("position", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_FromSize_t(__pyx_f_9pywrapfst_18MutableArcIterator_position(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3125, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_FromSize_t(__pyx_f_9pywrapfst_18MutableArcIterator_position(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3143, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -34029,7 +33246,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_10position(struct __py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3136
+/* "pywrapfst.pyx":3154
  *     return self._aiter.get().Position()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -34048,37 +33265,50 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_reset(struct __pyx_obj_9pywr
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3136, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_13reset)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3154, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_18MutableArcIterator_13reset)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3154, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3136, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3136, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3142
+  /* "pywrapfst.pyx":3160
  *     Resets the iterator to the initial position.
  *     """
  *     self._aiter.get().Reset()             # <<<<<<<<<<<<<<
@@ -34087,11 +33317,11 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_reset(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3142, __pyx_L1_error)
+    __PYX_ERR(0, 3160, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.get()->Reset();
 
-  /* "pywrapfst.pyx":3136
+  /* "pywrapfst.pyx":3154
  *     return self._aiter.get().Position()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -34131,7 +33361,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_12reset(struct __pyx_o
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("reset", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3136, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3154, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -34148,7 +33378,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_12reset(struct __pyx_o
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3144
+/* "pywrapfst.pyx":3162
  *     self._aiter.get().Reset()
  * 
  *   cpdef void seek(self, size_t a):             # <<<<<<<<<<<<<<
@@ -34164,72 +33394,57 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_seek(struct __pyx_obj_9pywra
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
   __Pyx_RefNannySetupContext("seek", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_seek); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3144, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_15seek)) {
-      __pyx_t_3 = __Pyx_PyInt_FromSize_t(__pyx_v_a); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3144, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_4, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_seek); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3162, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_18MutableArcIterator_15seek)) {
+        __pyx_t_3 = __Pyx_PyInt_FromSize_t(__pyx_v_a); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3162, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_4 = __pyx_t_1; __pyx_t_5 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+          __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+          if (likely(__pyx_t_5)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+            __Pyx_INCREF(__pyx_t_5);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_4, function);
+          }
         }
-      }
-      if (!__pyx_t_5) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3144, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3162, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3144, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_3};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3144, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        } else
-        #endif
-        {
-          __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3144, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL;
-          __Pyx_GIVEREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3144, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3153
+  /* "pywrapfst.pyx":3171
  *       a: The position to seek to.
  *     """
  *     self._aiter.get().Seek(a)             # <<<<<<<<<<<<<<
@@ -34238,11 +33453,11 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_seek(struct __pyx_obj_9pywra
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3153, __pyx_L1_error)
+    __PYX_ERR(0, 3171, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.get()->Seek(__pyx_v_a);
 
-  /* "pywrapfst.pyx":3144
+  /* "pywrapfst.pyx":3162
  *     self._aiter.get().Reset()
  * 
  *   cpdef void seek(self, size_t a):             # <<<<<<<<<<<<<<
@@ -34258,7 +33473,6 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_seek(struct __pyx_obj_9pywra
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
   __Pyx_WriteUnraisable("pywrapfst.MutableArcIterator.seek", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -34273,7 +33487,7 @@ static PyObject *__pyx_pw_9pywrapfst_18MutableArcIterator_15seek(PyObject *__pyx
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("seek (wrapper)", 0);
   assert(__pyx_arg_a); {
-    __pyx_v_a = __Pyx_PyInt_As_size_t(__pyx_arg_a); if (unlikely((__pyx_v_a == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 3144, __pyx_L3_error)
+    __pyx_v_a = __Pyx_PyInt_As_size_t(__pyx_arg_a); if (unlikely((__pyx_v_a == (size_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 3162, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -34294,7 +33508,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_14seek(struct __pyx_ob
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("seek", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_seek(__pyx_v_self, __pyx_v_a, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3144, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_seek(__pyx_v_self, __pyx_v_a, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3162, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -34311,7 +33525,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_14seek(struct __pyx_ob
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3155
+/* "pywrapfst.pyx":3173
  *     self._aiter.get().Seek(a)
  * 
  *   cpdef void set_flags(self, uint32 flags, uint32 mask):             # <<<<<<<<<<<<<<
@@ -34334,72 +33548,88 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_set_flags(struct __pyx_obj_9
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3155, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_17set_flags)) {
-      __pyx_t_3 = __Pyx_PyInt_From_uint32_t(__pyx_v_flags); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3155, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = __Pyx_PyInt_From_uint32_t(__pyx_v_mask); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3155, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
-      __pyx_t_7 = 0;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
-        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
-        if (likely(__pyx_t_6)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-          __Pyx_INCREF(__pyx_t_6);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_5, function);
-          __pyx_t_7 = 1;
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3173, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_18MutableArcIterator_17set_flags)) {
+        __pyx_t_3 = __Pyx_PyInt_From_uint32_t(__pyx_v_flags); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3173, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_4 = __Pyx_PyInt_From_uint32_t(__pyx_v_mask); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3173, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_5 = __pyx_t_1; __pyx_t_6 = NULL;
+        __pyx_t_7 = 0;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
+          __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+          if (likely(__pyx_t_6)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+            __Pyx_INCREF(__pyx_t_6);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_5, function);
+            __pyx_t_7 = 1;
+          }
         }
+        #if CYTHON_FAST_PYCALL
+        if (PyFunction_Check(__pyx_t_5)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
+          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3173, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        } else
+        #endif
+        #if CYTHON_FAST_PYCCALL
+        if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
+          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3173, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        } else
+        #endif
+        {
+          __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3173, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_8);
+          if (__pyx_t_6) {
+            __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
+          }
+          __Pyx_GIVEREF(__pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_3);
+          __Pyx_GIVEREF(__pyx_t_4);
+          PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_4);
+          __pyx_t_3 = 0;
+          __pyx_t_4 = 0;
+          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3173, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+        }
+        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3155, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_4};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3155, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3155, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        if (__pyx_t_6) {
-          __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        }
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_3);
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_4);
-        __pyx_t_3 = 0;
-        __pyx_t_4 = 0;
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3155, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3165
+  /* "pywrapfst.pyx":3183
  *       mask: A mask to be applied to the `flags` argument before setting them.
  *     """
  *     self._aiter.get().SetFlags(flags, mask)             # <<<<<<<<<<<<<<
@@ -34408,11 +33638,11 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_set_flags(struct __pyx_obj_9
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3165, __pyx_L1_error)
+    __PYX_ERR(0, 3183, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.get()->SetFlags(__pyx_v_flags, __pyx_v_mask);
 
-  /* "pywrapfst.pyx":3155
+  /* "pywrapfst.pyx":3173
  *     self._aiter.get().Seek(a)
  * 
  *   cpdef void set_flags(self, uint32 flags, uint32 mask):             # <<<<<<<<<<<<<<
@@ -34467,11 +33697,11 @@ static PyObject *__pyx_pw_9pywrapfst_18MutableArcIterator_17set_flags(PyObject *
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mask)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("set_flags", 1, 2, 2, 1); __PYX_ERR(0, 3155, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("set_flags", 1, 2, 2, 1); __PYX_ERR(0, 3173, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_flags") < 0)) __PYX_ERR(0, 3155, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_flags") < 0)) __PYX_ERR(0, 3173, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -34479,12 +33709,12 @@ static PyObject *__pyx_pw_9pywrapfst_18MutableArcIterator_17set_flags(PyObject *
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __pyx_v_flags = __Pyx_PyInt_As_uint32_t(values[0]); if (unlikely((__pyx_v_flags == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3155, __pyx_L3_error)
-    __pyx_v_mask = __Pyx_PyInt_As_uint32_t(values[1]); if (unlikely((__pyx_v_mask == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3155, __pyx_L3_error)
+    __pyx_v_flags = __Pyx_PyInt_As_uint32_t(values[0]); if (unlikely((__pyx_v_flags == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3173, __pyx_L3_error)
+    __pyx_v_mask = __Pyx_PyInt_As_uint32_t(values[1]); if (unlikely((__pyx_v_mask == ((uint32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3173, __pyx_L3_error)
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("set_flags", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3155, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("set_flags", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3173, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.MutableArcIterator.set_flags", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -34503,7 +33733,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_16set_flags(struct __p
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("set_flags", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_set_flags(__pyx_v_self, __pyx_v_flags, __pyx_v_mask, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3155, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_set_flags(__pyx_v_self, __pyx_v_flags, __pyx_v_mask, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3173, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -34520,7 +33750,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_16set_flags(struct __p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3167
+/* "pywrapfst.pyx":3185
  *     self._aiter.get().SetFlags(flags, mask)
  * 
  *   cpdef void set_value(self, Arc arc):             # <<<<<<<<<<<<<<
@@ -34535,67 +33765,54 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_set_value(struct __pyx_obj_9
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("set_value", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3167, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_19set_value)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_set_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3185, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_18MutableArcIterator_19set_value)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_arc)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3167, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, ((PyObject *)__pyx_v_arc)) : __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_arc));
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3185, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_arc)};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3167, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_arc)};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3167, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3167, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(((PyObject *)__pyx_v_arc));
-          __Pyx_GIVEREF(((PyObject *)__pyx_v_arc));
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, ((PyObject *)__pyx_v_arc));
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3167, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3176
+  /* "pywrapfst.pyx":3194
  *       arc: The arc to replace the current arc with.
  *     """
  *     self._aiter.get().SetValue(deref(arc._arc))             # <<<<<<<<<<<<<<
@@ -34604,15 +33821,15 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_set_value(struct __pyx_obj_9
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3176, __pyx_L1_error)
+    __PYX_ERR(0, 3194, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_arc) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc");
-    __PYX_ERR(0, 3176, __pyx_L1_error)
+    __PYX_ERR(0, 3194, __pyx_L1_error)
   }
   __pyx_v_self->_aiter.get()->SetValue((*__pyx_v_arc->_arc));
 
-  /* "pywrapfst.pyx":3167
+  /* "pywrapfst.pyx":3185
  *     self._aiter.get().SetFlags(flags, mask)
  * 
  *   cpdef void set_value(self, Arc arc):             # <<<<<<<<<<<<<<
@@ -34627,7 +33844,6 @@ static void __pyx_f_9pywrapfst_18MutableArcIterator_set_value(struct __pyx_obj_9
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_WriteUnraisable("pywrapfst.MutableArcIterator.set_value", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -34640,7 +33856,7 @@ static PyObject *__pyx_pw_9pywrapfst_18MutableArcIterator_19set_value(PyObject *
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("set_value (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_arc), __pyx_ptype_9pywrapfst_Arc, 1, "arc", 0))) __PYX_ERR(0, 3167, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_arc), __pyx_ptype_9pywrapfst_Arc, 1, "arc", 0))) __PYX_ERR(0, 3185, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_18MutableArcIterator_18set_value(((struct __pyx_obj_9pywrapfst_MutableArcIterator *)__pyx_v_self), ((struct __pyx_obj_9pywrapfst_Arc *)__pyx_v_arc));
 
   /* function exit code */
@@ -34658,7 +33874,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_18set_value(struct __p
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("set_value", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_set_value(__pyx_v_self, __pyx_v_arc, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3167, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_18MutableArcIterator_set_value(__pyx_v_self, __pyx_v_arc, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3185, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -34675,7 +33891,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_18set_value(struct __p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3178
+/* "pywrapfst.pyx":3196
  *     self._aiter.get().SetValue(deref(arc._arc))
  * 
  *   cpdef object value(self):             # <<<<<<<<<<<<<<
@@ -34695,39 +33911,52 @@ static PyObject *__pyx_f_9pywrapfst_18MutableArcIterator_value(struct __pyx_obj_
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3178, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_21value)) {
-      __Pyx_XDECREF(__pyx_r);
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3196, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_18MutableArcIterator_21value)) {
+        __Pyx_XDECREF(__pyx_r);
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3196, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_r = __pyx_t_2;
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3178, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3178, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_r = __pyx_t_2;
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3184
+  /* "pywrapfst.pyx":3202
  *     Returns the current arc.
  *     """
  *     return _init_Arc(self._aiter.get().Value())             # <<<<<<<<<<<<<<
@@ -34737,15 +33966,15 @@ static PyObject *__pyx_f_9pywrapfst_18MutableArcIterator_value(struct __pyx_obj_
   __Pyx_XDECREF(__pyx_r);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_aiter");
-    __PYX_ERR(0, 3184, __pyx_L1_error)
+    __PYX_ERR(0, 3202, __pyx_L1_error)
   }
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_Arc(__pyx_v_self->_aiter.get()->Value())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3184, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_Arc(__pyx_v_self->_aiter.get()->Value())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3202, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3178
+  /* "pywrapfst.pyx":3196
  *     self._aiter.get().SetValue(deref(arc._arc))
  * 
  *   cpdef object value(self):             # <<<<<<<<<<<<<<
@@ -34787,7 +34016,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_20value(struct __pyx_o
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("value", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_9pywrapfst_18MutableArcIterator_value(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3178, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_18MutableArcIterator_value(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3196, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -34835,7 +34064,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_22__reduce_cython__(CY
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._aiter,self._mfst cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__63, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__27, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -34888,7 +34117,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_24__setstate_cython__(
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._aiter,self._mfst cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__64, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__28, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -34911,7 +34140,7 @@ static PyObject *__pyx_pf_9pywrapfst_18MutableArcIterator_24__setstate_cython__(
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3198
+/* "pywrapfst.pyx":3216
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -34939,10 +34168,9 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator___repr__(struct __pyx_obj_9
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":3199
+  /* "pywrapfst.pyx":3217
  * 
  *   def __repr__(self):
  *     return "<StateIterator at 0x{:x}>".format(id(self))             # <<<<<<<<<<<<<<
@@ -34950,9 +34178,9 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator___repr__(struct __pyx_obj_9
  *   def __init__(self, _Fst ifst):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_StateIterator_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3199, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_StateIterator_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3217, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3199, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3217, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
@@ -34964,47 +34192,17 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator___repr__(struct __pyx_obj_9
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3199, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3199, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3199, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3199, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3199, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3217, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3198
+  /* "pywrapfst.pyx":3216
  *   """
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -35018,7 +34216,6 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator___repr__(struct __pyx_obj_9
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst.StateIterator.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -35027,7 +34224,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator___repr__(struct __pyx_obj_9
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3201
+/* "pywrapfst.pyx":3219
  *     return "<StateIterator at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, _Fst ifst):             # <<<<<<<<<<<<<<
@@ -35061,7 +34258,7 @@ static int __pyx_pw_9pywrapfst_13StateIterator_3__init__(PyObject *__pyx_v_self,
         else goto __pyx_L5_argtuple_error;
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 3201, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 3219, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
       goto __pyx_L5_argtuple_error;
@@ -35072,13 +34269,13 @@ static int __pyx_pw_9pywrapfst_13StateIterator_3__init__(PyObject *__pyx_v_self,
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3201, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3219, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.StateIterator.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3201, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3219, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_13StateIterator_2__init__(((struct __pyx_obj_9pywrapfst_StateIterator *)__pyx_v_self), __pyx_v_ifst);
 
   /* function exit code */
@@ -35096,7 +34293,7 @@ static int __pyx_pf_9pywrapfst_13StateIterator_2__init__(struct __pyx_obj_9pywra
   std::shared_ptr<fst::script::FstClass>  __pyx_t_1;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":3203
+  /* "pywrapfst.pyx":3221
  *   def __init__(self, _Fst ifst):
  *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
  *     self._fst = ifst._fst             # <<<<<<<<<<<<<<
@@ -35105,16 +34302,16 @@ static int __pyx_pf_9pywrapfst_13StateIterator_2__init__(struct __pyx_obj_9pywra
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3203, __pyx_L1_error)
+    __PYX_ERR(0, 3221, __pyx_L1_error)
   }
   __pyx_t_1 = __pyx_v_ifst->_fst;
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3203, __pyx_L1_error)
+    __PYX_ERR(0, 3221, __pyx_L1_error)
   }
   __pyx_v_self->_fst = __pyx_t_1;
 
-  /* "pywrapfst.pyx":3204
+  /* "pywrapfst.pyx":3222
  *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
  *     self._fst = ifst._fst
  *     self._siter.reset(new fst.StateIteratorClass(deref(self._fst)))             # <<<<<<<<<<<<<<
@@ -35123,15 +34320,15 @@ static int __pyx_pf_9pywrapfst_13StateIterator_2__init__(struct __pyx_obj_9pywra
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 3204, __pyx_L1_error)
+    __PYX_ERR(0, 3222, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3204, __pyx_L1_error)
+    __PYX_ERR(0, 3222, __pyx_L1_error)
   }
   __pyx_v_self->_siter.reset(new fst::script::StateIteratorClass((*__pyx_v_self->_fst)));
 
-  /* "pywrapfst.pyx":3201
+  /* "pywrapfst.pyx":3219
  *     return "<StateIterator at 0x{:x}>".format(id(self))
  * 
  *   def __init__(self, _Fst ifst):             # <<<<<<<<<<<<<<
@@ -35150,7 +34347,7 @@ static int __pyx_pf_9pywrapfst_13StateIterator_2__init__(struct __pyx_obj_9pywra
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3207
+/* "pywrapfst.pyx":3225
  * 
  *   # This just registers this class as a possible iterator.
  *   def __iter__(self):             # <<<<<<<<<<<<<<
@@ -35176,7 +34373,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_4__iter__(struct __pyx_obj_
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__iter__", 0);
 
-  /* "pywrapfst.pyx":3208
+  /* "pywrapfst.pyx":3226
  *   # This just registers this class as a possible iterator.
  *   def __iter__(self):
  *     return self             # <<<<<<<<<<<<<<
@@ -35188,7 +34385,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_4__iter__(struct __pyx_obj_
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3207
+  /* "pywrapfst.pyx":3225
  * 
  *   # This just registers this class as a possible iterator.
  *   def __iter__(self):             # <<<<<<<<<<<<<<
@@ -35203,7 +34400,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_4__iter__(struct __pyx_obj_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3211
+/* "pywrapfst.pyx":3229
  * 
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):             # <<<<<<<<<<<<<<
@@ -35232,7 +34429,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_6__next__(struct __pyx_obj_
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("__next__", 0);
 
-  /* "pywrapfst.pyx":3212
+  /* "pywrapfst.pyx":3230
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):
  *     if self.done():             # <<<<<<<<<<<<<<
@@ -35241,12 +34438,12 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_6__next__(struct __pyx_obj_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "done");
-    __PYX_ERR(0, 3212, __pyx_L1_error)
+    __PYX_ERR(0, 3230, __pyx_L1_error)
   }
   __pyx_t_1 = (((struct __pyx_vtabstruct_9pywrapfst_StateIterator *)__pyx_v_self->__pyx_vtab)->done(__pyx_v_self, 0) != 0);
   if (unlikely(__pyx_t_1)) {
 
-    /* "pywrapfst.pyx":3213
+    /* "pywrapfst.pyx":3231
  *   def __next__(self):
  *     if self.done():
  *       raise StopIteration             # <<<<<<<<<<<<<<
@@ -35254,9 +34451,9 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_6__next__(struct __pyx_obj_
  *     self.next()
  */
     __Pyx_Raise(__pyx_builtin_StopIteration, 0, 0, 0);
-    __PYX_ERR(0, 3213, __pyx_L1_error)
+    __PYX_ERR(0, 3231, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":3212
+    /* "pywrapfst.pyx":3230
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):
  *     if self.done():             # <<<<<<<<<<<<<<
@@ -35265,7 +34462,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_6__next__(struct __pyx_obj_
  */
   }
 
-  /* "pywrapfst.pyx":3214
+  /* "pywrapfst.pyx":3232
  *     if self.done():
  *       raise StopIteration
  *     cdef int64 result = self.value()             # <<<<<<<<<<<<<<
@@ -35274,11 +34471,11 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_6__next__(struct __pyx_obj_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "value");
-    __PYX_ERR(0, 3214, __pyx_L1_error)
+    __PYX_ERR(0, 3232, __pyx_L1_error)
   }
   __pyx_v_result = ((struct __pyx_vtabstruct_9pywrapfst_StateIterator *)__pyx_v_self->__pyx_vtab)->value(__pyx_v_self, 0);
 
-  /* "pywrapfst.pyx":3215
+  /* "pywrapfst.pyx":3233
  *       raise StopIteration
  *     cdef int64 result = self.value()
  *     self.next()             # <<<<<<<<<<<<<<
@@ -35287,11 +34484,11 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_6__next__(struct __pyx_obj_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "next");
-    __PYX_ERR(0, 3215, __pyx_L1_error)
+    __PYX_ERR(0, 3233, __pyx_L1_error)
   }
   ((struct __pyx_vtabstruct_9pywrapfst_StateIterator *)__pyx_v_self->__pyx_vtab)->next(__pyx_v_self, 0);
 
-  /* "pywrapfst.pyx":3216
+  /* "pywrapfst.pyx":3234
  *     cdef int64 result = self.value()
  *     self.next()
  *     return result             # <<<<<<<<<<<<<<
@@ -35299,13 +34496,13 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_6__next__(struct __pyx_obj_
  *   cpdef bool done(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_v_result); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3216, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_v_result); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3234, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3211
+  /* "pywrapfst.pyx":3229
  * 
  *   # Magic method used to get a Pythonic API out of the C++ API.
  *   def __next__(self):             # <<<<<<<<<<<<<<
@@ -35324,7 +34521,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_6__next__(struct __pyx_obj_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3218
+/* "pywrapfst.pyx":3236
  *     return result
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -35345,39 +34542,52 @@ static bool __pyx_f_9pywrapfst_13StateIterator_done(struct __pyx_obj_9pywrapfst_
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3218, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_13StateIterator_9done)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3236, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_13StateIterator_9done)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3236, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3236, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3218, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3218, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3218, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3227
+  /* "pywrapfst.pyx":3245
  *       True if the iterator is exhausted, False otherwise.
  *     """
  *     return self._siter.get().Done()             # <<<<<<<<<<<<<<
@@ -35386,12 +34596,12 @@ static bool __pyx_f_9pywrapfst_13StateIterator_done(struct __pyx_obj_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 3227, __pyx_L1_error)
+    __PYX_ERR(0, 3245, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_siter.get()->Done();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3218
+  /* "pywrapfst.pyx":3236
  *     return result
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -35432,7 +34642,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_8done(struct __pyx_obj_9pyw
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("done", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_13StateIterator_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3218, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_13StateIterator_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3236, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -35449,7 +34659,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_8done(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3229
+/* "pywrapfst.pyx":3247
  *     return self._siter.get().Done()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -35468,37 +34678,50 @@ static void __pyx_f_9pywrapfst_13StateIterator_next(struct __pyx_obj_9pywrapfst_
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3229, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_13StateIterator_11next)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3247, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_13StateIterator_11next)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3247, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3229, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3229, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3235
+  /* "pywrapfst.pyx":3253
  *     Advances the iterator.
  *     """
  *     self._siter.get().Next()             # <<<<<<<<<<<<<<
@@ -35507,11 +34730,11 @@ static void __pyx_f_9pywrapfst_13StateIterator_next(struct __pyx_obj_9pywrapfst_
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 3235, __pyx_L1_error)
+    __PYX_ERR(0, 3253, __pyx_L1_error)
   }
   __pyx_v_self->_siter.get()->Next();
 
-  /* "pywrapfst.pyx":3229
+  /* "pywrapfst.pyx":3247
  *     return self._siter.get().Done()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -35551,7 +34774,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_10next(struct __pyx_obj_9py
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("next", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_13StateIterator_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3229, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_13StateIterator_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3247, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -35568,7 +34791,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_10next(struct __pyx_obj_9py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3237
+/* "pywrapfst.pyx":3255
  *     self._siter.get().Next()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -35587,37 +34810,50 @@ static void __pyx_f_9pywrapfst_13StateIterator_reset(struct __pyx_obj_9pywrapfst
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3237, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_13StateIterator_13reset)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3255, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_13StateIterator_13reset)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3255, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3237, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3237, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3243
+  /* "pywrapfst.pyx":3261
  *     Resets the iterator to the initial position.
  *     """
  *     self._siter.get().Reset()             # <<<<<<<<<<<<<<
@@ -35626,11 +34862,11 @@ static void __pyx_f_9pywrapfst_13StateIterator_reset(struct __pyx_obj_9pywrapfst
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 3243, __pyx_L1_error)
+    __PYX_ERR(0, 3261, __pyx_L1_error)
   }
   __pyx_v_self->_siter.get()->Reset();
 
-  /* "pywrapfst.pyx":3237
+  /* "pywrapfst.pyx":3255
  *     self._siter.get().Next()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -35670,7 +34906,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_12reset(struct __pyx_obj_9p
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("reset", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_13StateIterator_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3237, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_13StateIterator_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3255, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -35687,7 +34923,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_12reset(struct __pyx_obj_9p
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3245
+/* "pywrapfst.pyx":3263
  *     self._siter.get().Reset()
  * 
  *   cpdef int64 value(self):             # <<<<<<<<<<<<<<
@@ -35708,39 +34944,52 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_13StateIterator_value(struc
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3245, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_13StateIterator_15value)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_value); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3263, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_13StateIterator_15value)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3263, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3263, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3245, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3245, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3245, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":3251
+  /* "pywrapfst.pyx":3269
  *     Returns the current state index.
  *     """
  *     return self._siter.get().Value()             # <<<<<<<<<<<<<<
@@ -35749,12 +34998,12 @@ static __pyx_t_10basictypes_int64 __pyx_f_9pywrapfst_13StateIterator_value(struc
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_siter");
-    __PYX_ERR(0, 3251, __pyx_L1_error)
+    __PYX_ERR(0, 3269, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_siter.get()->Value();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3245
+  /* "pywrapfst.pyx":3263
  *     self._siter.get().Reset()
  * 
  *   cpdef int64 value(self):             # <<<<<<<<<<<<<<
@@ -35795,7 +35044,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_14value(struct __pyx_obj_9p
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("value", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_13StateIterator_value(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3245, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_f_9pywrapfst_13StateIterator_value(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3263, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -35843,7 +35092,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_16__reduce_cython__(CYTHON_
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._fst,self._siter cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__65, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__29, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -35896,7 +35145,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_18__setstate_cython__(CYTHO
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._fst,self._siter cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__66, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__30, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -35919,7 +35168,7 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_18__setstate_cython__(CYTHO
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3257
+/* "pywrapfst.pyx":3275
  * 
  * 
  * cdef _Fst _map(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -35928,11 +35177,11 @@ static PyObject *__pyx_pf_9pywrapfst_13StateIterator_18__setstate_cython__(CYTHO
  */
 
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, struct __pyx_opt_args_9pywrapfst__map *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__67;
+  float __pyx_v_delta = __pyx_k__31;
   PyObject *__pyx_v_map_type = ((PyObject *)__pyx_n_b_identity);
   double __pyx_v_power = ((double)1.);
 
-  /* "pywrapfst.pyx":3261
+  /* "pywrapfst.pyx":3279
  *                map_type=b"identity",
  *                double power=1.,
  *                weight=None):             # <<<<<<<<<<<<<<
@@ -35951,9 +35200,8 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
+  fst::script::WeightClass __pyx_t_8;
   fst::script::WeightClass __pyx_t_9;
-  fst::script::WeightClass __pyx_t_10;
   __Pyx_RefNannySetupContext("_map", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -35970,27 +35218,27 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
     }
   }
 
-  /* "pywrapfst.pyx":3263
+  /* "pywrapfst.pyx":3281
  *                weight=None):
  *   cdef fst.MapType map_type_enum
  *   if not fst.GetMapType(tostring(map_type), addr(map_type_enum)):             # <<<<<<<<<<<<<<
  *     raise FstArgError("Unknown map type: {!r}".format(map_type))
  *   cdef fst.WeightClass wc = (_get_WeightClass_or_One(ifst.weight_type(),
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_map_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3263, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_map_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3281, __pyx_L1_error)
   __pyx_t_2 = ((!(fst::script::GetMapType(__pyx_t_1, (&__pyx_v_map_type_enum)) != 0)) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":3264
+    /* "pywrapfst.pyx":3282
  *   cdef fst.MapType map_type_enum
  *   if not fst.GetMapType(tostring(map_type), addr(map_type_enum)):
  *     raise FstArgError("Unknown map type: {!r}".format(map_type))             # <<<<<<<<<<<<<<
  *   cdef fst.WeightClass wc = (_get_WeightClass_or_One(ifst.weight_type(),
  *       weight) if map_type_enum == fst.TIMES_MAPPER else
  */
-    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3264, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3282, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_map_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3264, __pyx_L1_error)
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_map_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3282, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
@@ -36002,38 +35250,10 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
         __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_map_type); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3264, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_map_type};
-        __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3264, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_map_type};
-        __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3264, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_5);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3264, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_INCREF(__pyx_v_map_type);
-        __Pyx_GIVEREF(__pyx_v_map_type);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_v_map_type);
-        __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3264, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_v_map_type) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_map_type);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3282, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __pyx_t_6 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
@@ -36045,47 +35265,17 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
         __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
-    if (!__pyx_t_6) {
-      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3264, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3264, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_5};
-        __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3264, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3264, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_5);
-        __pyx_t_5 = 0;
-        __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_8, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3264, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-    }
+    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3282, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 3264, __pyx_L1_error)
+    __PYX_ERR(0, 3282, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":3263
+    /* "pywrapfst.pyx":3281
  *                weight=None):
  *   cdef fst.MapType map_type_enum
  *   if not fst.GetMapType(tostring(map_type), addr(map_type_enum)):             # <<<<<<<<<<<<<<
@@ -36094,7 +35284,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
  */
   }
 
-  /* "pywrapfst.pyx":3266
+  /* "pywrapfst.pyx":3284
  *     raise FstArgError("Unknown map type: {!r}".format(map_type))
  *   cdef fst.WeightClass wc = (_get_WeightClass_or_One(ifst.weight_type(),
  *       weight) if map_type_enum == fst.TIMES_MAPPER else             # <<<<<<<<<<<<<<
@@ -36103,7 +35293,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
  */
   if (((__pyx_v_map_type_enum == fst::script::TIMES_MAPPER) != 0)) {
 
-    /* "pywrapfst.pyx":3265
+    /* "pywrapfst.pyx":3283
  *   if not fst.GetMapType(tostring(map_type), addr(map_type_enum)):
  *     raise FstArgError("Unknown map type: {!r}".format(map_type))
  *   cdef fst.WeightClass wc = (_get_WeightClass_or_One(ifst.weight_type(),             # <<<<<<<<<<<<<<
@@ -36112,21 +35302,21 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
  */
     if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-      __PYX_ERR(0, 3265, __pyx_L1_error)
+      __PYX_ERR(0, 3283, __pyx_L1_error)
     }
 
-    /* "pywrapfst.pyx":3266
+    /* "pywrapfst.pyx":3284
  *     raise FstArgError("Unknown map type: {!r}".format(map_type))
  *   cdef fst.WeightClass wc = (_get_WeightClass_or_One(ifst.weight_type(),
  *       weight) if map_type_enum == fst.TIMES_MAPPER else             # <<<<<<<<<<<<<<
  *       _get_WeightClass_or_Zero(ifst.weight_type(), weight))
  *   return _init_XFst(fst.Map(deref(ifst._fst), map_type_enum, delta, power, wc))
  */
-    __pyx_t_10 = __pyx_f_9pywrapfst__get_WeightClass_or_One(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3265, __pyx_L1_error)
-    __pyx_t_9 = __pyx_t_10;
+    __pyx_t_9 = __pyx_f_9pywrapfst__get_WeightClass_or_One(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3283, __pyx_L1_error)
+    __pyx_t_8 = __pyx_t_9;
   } else {
 
-    /* "pywrapfst.pyx":3267
+    /* "pywrapfst.pyx":3285
  *   cdef fst.WeightClass wc = (_get_WeightClass_or_One(ifst.weight_type(),
  *       weight) if map_type_enum == fst.TIMES_MAPPER else
  *       _get_WeightClass_or_Zero(ifst.weight_type(), weight))             # <<<<<<<<<<<<<<
@@ -36135,14 +35325,14 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
  */
     if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-      __PYX_ERR(0, 3267, __pyx_L1_error)
+      __PYX_ERR(0, 3285, __pyx_L1_error)
     }
-    __pyx_t_10 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3267, __pyx_L1_error)
-    __pyx_t_9 = __pyx_t_10;
+    __pyx_t_9 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3285, __pyx_L1_error)
+    __pyx_t_8 = __pyx_t_9;
   }
-  __pyx_v_wc = __pyx_t_9;
+  __pyx_v_wc = __pyx_t_8;
 
-  /* "pywrapfst.pyx":3268
+  /* "pywrapfst.pyx":3286
  *       weight) if map_type_enum == fst.TIMES_MAPPER else
  *       _get_WeightClass_or_Zero(ifst.weight_type(), weight))
  *   return _init_XFst(fst.Map(deref(ifst._fst), map_type_enum, delta, power, wc))             # <<<<<<<<<<<<<<
@@ -36152,15 +35342,15 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
   __Pyx_XDECREF(((PyObject *)__pyx_r));
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3268, __pyx_L1_error)
+    __PYX_ERR(0, 3286, __pyx_L1_error)
   }
-  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(fst::script::Map((*__pyx_v_ifst->_fst), __pyx_v_map_type_enum, __pyx_v_delta, __pyx_v_power, __pyx_v_wc))); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3268, __pyx_L1_error)
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(fst::script::Map((*__pyx_v_ifst->_fst), __pyx_v_map_type_enum, __pyx_v_delta, __pyx_v_power, __pyx_v_wc))); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3286, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_3);
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3257
+  /* "pywrapfst.pyx":3275
  * 
  * 
  * cdef _Fst _map(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -36175,7 +35365,6 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
   __Pyx_AddTraceback("pywrapfst._map", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -36184,7 +35373,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3271
+/* "pywrapfst.pyx":3289
  * 
  * 
  * cpdef _Fst arcmap(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -36192,18 +35381,18 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst__map(struct __pyx_ob
  *                   map_type=b"identity",
  */
 
-static PyObject *__pyx_pw_9pywrapfst_17arcmap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_19arcmap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_arcmap(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_arcmap *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__68;
+  float __pyx_v_delta = __pyx_k__32;
   PyObject *__pyx_v_map_type = ((PyObject *)__pyx_n_b_identity);
   double __pyx_v_power = ((double)1.);
 
-  /* "pywrapfst.pyx":3275
+  /* "pywrapfst.pyx":3293
  *                   map_type=b"identity",
  *                   double power=1.,
  *                   weight=None):             # <<<<<<<<<<<<<<
  *   """
- *   arcmap(ifst, delta=0.0009765625, map_type="identity", weight=None)
+ *   arcmap(ifst, delta=0.0009765625, map_type="identity", power=1., weight=None)
  */
   PyObject *__pyx_v_weight = ((PyObject *)Py_None);
   struct __pyx_obj_9pywrapfst__Fst *__pyx_r = NULL;
@@ -36226,7 +35415,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_arcmap(struct __pyx_
     }
   }
 
-  /* "pywrapfst.pyx":3318
+  /* "pywrapfst.pyx":3336
  *   See also: `statemap`.
  *   """
  *   return _map(ifst, delta, map_type, power, weight)             # <<<<<<<<<<<<<<
@@ -36239,13 +35428,13 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_arcmap(struct __pyx_
   __pyx_t_2.map_type = __pyx_v_map_type;
   __pyx_t_2.power = __pyx_v_power;
   __pyx_t_2.weight = __pyx_v_weight;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__map(__pyx_v_ifst, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3318, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__map(__pyx_v_ifst, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3336, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3271
+  /* "pywrapfst.pyx":3289
  * 
  * 
  * cpdef _Fst arcmap(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -36265,9 +35454,9 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_arcmap(struct __pyx_
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_17arcmap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_16arcmap[] = "\n  arcmap(ifst, delta=0.0009765625, map_type=\"identity\", weight=None)\n\n  Constructively applies a transform to all arcs and final states.\n\n  This operation transforms each arc and final state in the input FST using\n  one of the following:\n\n    * identity: maps to self.\n    * input_epsilon: replaces all input labels with epsilon.\n    * invert: reciprocates all non-Zero weights.\n    * float_power: raises all weights to a floating-point power.\n    * output_epsilon: replaces all output labels with epsilon.\n    * quantize: quantizes weights.\n    * plus: adds a constant to all weights.\n    * power: raises all weights to an integral power.\n    * rmweight: replaces all non-Zero weights with 1.\n    * superfinal: redirects final states to a new superfinal state.\n    * times: right-multiplies a constant to all weights.\n    * to_log: converts weights to the log semiring.\n    * to_log64: converts weights to the log64 semiring.\n    * to_standard: converts weights to the tropical (\"standard\") semiring.\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta (ignored unless `map_type` is\n        `quantize`).\n    map_type: A string matching a known mapping operation (see above).\n    power: A positive scalar or integer power; ignored unless `map_type` is\n        `float_power` or `power` (in which case it defaults to 1).\n    weight: A Weight or weight string passed to the arc-mapper; ignored unless\n        `map_type` is `plus` (in which case it defaults to semiring Zero) or\n        `times` (in which case it defaults to semiring One).\n\n  Returns:\n    An FST with arcs and final states remapped.\n\n  Raises:\n    FstArgError: Unknown map type.\n\n  See also: `statemap`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_17arcmap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_19arcmap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_18arcmap[] = "\n  arcmap(ifst, delta=0.0009765625, map_type=\"identity\", power=1., weight=None)\n\n  Constructively applies a transform to all arcs and final states.\n\n  This operation transforms each arc and final state in the input FST using\n  one of the following:\n\n    * identity: maps to self.\n    * input_epsilon: replaces all input labels with epsilon.\n    * invert: reciprocates all non-Zero weights.\n    * float_power: raises all weights to a floating-point power.\n    * output_epsilon: replaces all output labels with epsilon.\n    * quantize: quantizes weights.\n    * plus: adds a constant to all weights.\n    * power: raises all weights to an integral power.\n    * rmweight: replaces all non-Zero weights with 1.\n    * superfinal: redirects final states to a new superfinal state.\n    * times: right-multiplies a constant by all weights.\n    * to_log: converts weights to the log semiring.\n    * to_log64: converts weights to the log64 semiring.\n    * to_standard: converts weights to the tropical (\"standard\") semiring.\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta (ignored unless `map_type` is\n        `quantize`).\n    map_type: A string matching a known mapping operation (see above).\n    power: A positive scalar or integer power; ignored unless `map_type` is\n        `float_power` or `power` (in which case it defaults to 1).\n    weight: A Weight or weight string passed to the arc-mapper; ignored unless\n        `map_type` is `plus` (in which case it defaults to semiring Zero) or\n        `times` (in which case it defaults to semiring One).\n\n  Returns:\n    An FST with arcs and final states remapped.\n\n  Raises:\n    FstArgError: Unknown map type.\n\n  See also: `statemap`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_19arcmap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   float __pyx_v_delta;
   PyObject *__pyx_v_map_type = 0;
@@ -36281,12 +35470,12 @@ static PyObject *__pyx_pw_9pywrapfst_17arcmap(PyObject *__pyx_self, PyObject *__
     PyObject* values[5] = {0,0,0,0,0};
     values[2] = ((PyObject *)__pyx_n_b_identity);
 
-    /* "pywrapfst.pyx":3275
+    /* "pywrapfst.pyx":3293
  *                   map_type=b"identity",
  *                   double power=1.,
  *                   weight=None):             # <<<<<<<<<<<<<<
  *   """
- *   arcmap(ifst, delta=0.0009765625, map_type="identity", weight=None)
+ *   arcmap(ifst, delta=0.0009765625, map_type="identity", power=1., weight=None)
  */
     values[4] = ((PyObject *)Py_None);
     if (unlikely(__pyx_kwds)) {
@@ -36337,7 +35526,7 @@ static PyObject *__pyx_pw_9pywrapfst_17arcmap(PyObject *__pyx_self, PyObject *__
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "arcmap") < 0)) __PYX_ERR(0, 3271, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "arcmap") < 0)) __PYX_ERR(0, 3289, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -36356,13 +35545,13 @@ static PyObject *__pyx_pw_9pywrapfst_17arcmap(PyObject *__pyx_self, PyObject *__
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3272, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3290, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__68;
+      __pyx_v_delta = __pyx_k__32;
     }
     __pyx_v_map_type = values[2];
     if (values[3]) {
-      __pyx_v_power = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_power == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3274, __pyx_L3_error)
+      __pyx_v_power = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_power == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3292, __pyx_L3_error)
     } else {
       __pyx_v_power = ((double)1.);
     }
@@ -36370,16 +35559,16 @@ static PyObject *__pyx_pw_9pywrapfst_17arcmap(PyObject *__pyx_self, PyObject *__
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("arcmap", 0, 1, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3271, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("arcmap", 0, 1, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3289, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.arcmap", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3271, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_16arcmap(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_map_type, __pyx_v_power, __pyx_v_weight);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3289, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_18arcmap(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_map_type, __pyx_v_power, __pyx_v_weight);
 
-  /* "pywrapfst.pyx":3271
+  /* "pywrapfst.pyx":3289
  * 
  * 
  * cpdef _Fst arcmap(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -36396,7 +35585,7 @@ static PyObject *__pyx_pw_9pywrapfst_17arcmap(PyObject *__pyx_self, PyObject *__
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_16arcmap(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, PyObject *__pyx_v_map_type, double __pyx_v_power, PyObject *__pyx_v_weight) {
+static PyObject *__pyx_pf_9pywrapfst_18arcmap(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, PyObject *__pyx_v_map_type, double __pyx_v_power, PyObject *__pyx_v_weight) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -36408,7 +35597,7 @@ static PyObject *__pyx_pf_9pywrapfst_16arcmap(CYTHON_UNUSED PyObject *__pyx_self
   __pyx_t_2.map_type = __pyx_v_map_type;
   __pyx_t_2.power = __pyx_v_power;
   __pyx_t_2.weight = __pyx_v_weight;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_arcmap(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3271, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_arcmap(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3289, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -36425,7 +35614,7 @@ static PyObject *__pyx_pf_9pywrapfst_16arcmap(CYTHON_UNUSED PyObject *__pyx_self
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3321
+/* "pywrapfst.pyx":3339
  * 
  * 
  * cpdef _MutableFst compose(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -36433,11 +35622,11 @@ static PyObject *__pyx_pf_9pywrapfst_16arcmap(CYTHON_UNUSED PyObject *__pyx_self
  *                           compose_filter=b"auto",
  */
 
-static PyObject *__pyx_pw_9pywrapfst_19compose(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_21compose(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_compose(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_compose *__pyx_optional_args) {
   PyObject *__pyx_v_compose_filter = ((PyObject *)__pyx_n_b_auto);
 
-  /* "pywrapfst.pyx":3324
+  /* "pywrapfst.pyx":3342
  *                           _Fst ifst2,
  *                           compose_filter=b"auto",
  *                           bool connect=True):             # <<<<<<<<<<<<<<
@@ -36462,7 +35651,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_compose(struc
     }
   }
 
-  /* "pywrapfst.pyx":3349
+  /* "pywrapfst.pyx":3367
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst1.arc_type()))             # <<<<<<<<<<<<<<
@@ -36471,21 +35660,21 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_compose(struc
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3349, __pyx_L1_error)
+    __PYX_ERR(0, 3367, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst1->__pyx_vtab)->arc_type(__pyx_v_ifst1, 0)));
 
-  /* "pywrapfst.pyx":3352
+  /* "pywrapfst.pyx":3370
  *   cdef unique_ptr[fst.ComposeOptions] opts
  *   opts.reset(new fst.ComposeOptions(connect,
  *       _get_compose_filter(tostring(compose_filter))))             # <<<<<<<<<<<<<<
  *   fst.Compose(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_compose_filter, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3352, __pyx_L1_error)
-  __pyx_t_2 = __pyx_f_9pywrapfst__get_compose_filter(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3352, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_compose_filter, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3370, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst__get_compose_filter(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3370, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":3351
+  /* "pywrapfst.pyx":3369
  *   tfst.reset(new fst.VectorFstClass(ifst1.arc_type()))
  *   cdef unique_ptr[fst.ComposeOptions] opts
  *   opts.reset(new fst.ComposeOptions(connect,             # <<<<<<<<<<<<<<
@@ -36494,7 +35683,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_compose(struc
  */
   __pyx_v_opts.reset(new fst::ComposeOptions(__pyx_v_connect, __pyx_t_2));
 
-  /* "pywrapfst.pyx":3353
+  /* "pywrapfst.pyx":3371
  *   opts.reset(new fst.ComposeOptions(connect,
  *       _get_compose_filter(tostring(compose_filter))))
  *   fst.Compose(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))             # <<<<<<<<<<<<<<
@@ -36503,15 +35692,15 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_compose(struc
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3353, __pyx_L1_error)
+    __PYX_ERR(0, 3371, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst2) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3353, __pyx_L1_error)
+    __PYX_ERR(0, 3371, __pyx_L1_error)
   }
   fst::script::Compose((*__pyx_v_ifst1->_fst), (*__pyx_v_ifst2->_fst), __pyx_v_tfst.get(), (*__pyx_v_opts));
 
-  /* "pywrapfst.pyx":3354
+  /* "pywrapfst.pyx":3372
  *       _get_compose_filter(tostring(compose_filter))))
  *   fst.Compose(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -36519,13 +35708,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_compose(struc
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3354, __pyx_L1_error)
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3372, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_3);
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3321
+  /* "pywrapfst.pyx":3339
  * 
  * 
  * cpdef _MutableFst compose(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -36545,9 +35734,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_compose(struc
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_19compose(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_18compose[] = "\n  compose(ifst1, ifst2, compose_filter=\"auto\", connect=True)\n\n  Constructively composes two FSTs.\n\n  This operation computes the composition of two FSTs. If A transduces string\n  x to y with weight a and B transduces y to z with weight b, then their\n  composition transduces string x to z with weight a \\otimes b. The output\n  labels of the first transducer or the input labels of the second transducer\n  must be sorted (or otherwise support appropriate matchers).\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    compose_filter: A string matching a known composition filter; one of:\n        \"alt_sequence\", \"auto\", \"match\", \"null\", \"sequence\", \"trivial\".\n    connect: Should output be trimmed?\n\n  Returns:\n    An FST.\n\n  See also: `arcsort`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_19compose(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_21compose(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_20compose[] = "\n  compose(ifst1, ifst2, compose_filter=\"auto\", connect=True)\n\n  Constructively composes two FSTs.\n\n  This operation computes the composition of two FSTs. If A transduces string\n  x to y with weight a and B transduces y to z with weight b, then their\n  composition transduces string x to z with weight a \\otimes b. The output\n  labels of the first transducer or the input labels of the second transducer\n  must be sorted (or otherwise support appropriate matchers).\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    compose_filter: A string matching a known composition filter; one of:\n        \"alt_sequence\", \"auto\", \"match\", \"null\", \"sequence\", \"trivial\".\n    connect: Should output be trimmed?\n\n  Returns:\n    An FST.\n\n  See also: `arcsort`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_21compose(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1 = 0;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2 = 0;
   PyObject *__pyx_v_compose_filter = 0;
@@ -36583,7 +35772,7 @@ static PyObject *__pyx_pw_9pywrapfst_19compose(PyObject *__pyx_self, PyObject *_
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ifst2)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("compose", 0, 2, 4, 1); __PYX_ERR(0, 3321, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("compose", 0, 2, 4, 1); __PYX_ERR(0, 3339, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
@@ -36599,7 +35788,7 @@ static PyObject *__pyx_pw_9pywrapfst_19compose(PyObject *__pyx_self, PyObject *_
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "compose") < 0)) __PYX_ERR(0, 3321, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "compose") < 0)) __PYX_ERR(0, 3339, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -36617,10 +35806,10 @@ static PyObject *__pyx_pw_9pywrapfst_19compose(PyObject *__pyx_self, PyObject *_
     __pyx_v_ifst2 = ((struct __pyx_obj_9pywrapfst__Fst *)values[1]);
     __pyx_v_compose_filter = values[2];
     if (values[3]) {
-      __pyx_v_connect = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_connect == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3324, __pyx_L3_error)
+      __pyx_v_connect = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_connect == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3342, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3324
+      /* "pywrapfst.pyx":3342
  *                           _Fst ifst2,
  *                           compose_filter=b"auto",
  *                           bool connect=True):             # <<<<<<<<<<<<<<
@@ -36632,17 +35821,17 @@ static PyObject *__pyx_pw_9pywrapfst_19compose(PyObject *__pyx_self, PyObject *_
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("compose", 0, 2, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3321, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("compose", 0, 2, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3339, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.compose", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3321, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3322, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_18compose(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_compose_filter, __pyx_v_connect);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3339, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3340, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_20compose(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_compose_filter, __pyx_v_connect);
 
-  /* "pywrapfst.pyx":3321
+  /* "pywrapfst.pyx":3339
  * 
  * 
  * cpdef _MutableFst compose(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -36659,7 +35848,7 @@ static PyObject *__pyx_pw_9pywrapfst_19compose(PyObject *__pyx_self, PyObject *_
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_18compose(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect) {
+static PyObject *__pyx_pf_9pywrapfst_20compose(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -36669,7 +35858,7 @@ static PyObject *__pyx_pf_9pywrapfst_18compose(CYTHON_UNUSED PyObject *__pyx_sel
   __pyx_t_2.__pyx_n = 2;
   __pyx_t_2.compose_filter = __pyx_v_compose_filter;
   __pyx_t_2.connect = __pyx_v_connect;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_compose(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3321, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_compose(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3339, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -36686,30 +35875,28 @@ static PyObject *__pyx_pf_9pywrapfst_18compose(CYTHON_UNUSED PyObject *__pyx_sel
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3357
+/* "pywrapfst.pyx":3375
  * 
  * 
- * cpdef _Fst convert(_Fst ifst, fst_type=None):             # <<<<<<<<<<<<<<
+ * cpdef _Fst convert(_Fst ifst, fst_type=b""):             # <<<<<<<<<<<<<<
  *   """
- *   convert(ifst, fst_type=None)
+ *   convert(ifst, fst_type="")
  */
 
-static PyObject *__pyx_pw_9pywrapfst_21convert(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_23convert(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_convert(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_convert *__pyx_optional_args) {
-  PyObject *__pyx_v_fst_type = ((PyObject *)Py_None);
+  PyObject *__pyx_v_fst_type = ((PyObject *)__pyx_kp_b__10);
   std::string __pyx_v_fst_type_string;
   std::unique_ptr<fst::script::FstClass>  __pyx_v_tfst;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   std::string __pyx_t_1;
   int __pyx_t_2;
-  std::string __pyx_t_3;
+  PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
-  PyObject *__pyx_t_9 = NULL;
   __Pyx_RefNannySetupContext("convert", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -36717,29 +35904,18 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_convert(struct __pyx
     }
   }
 
-  /* "pywrapfst.pyx":3374
+  /* "pywrapfst.pyx":3392
  *     FstOpError: Conversion failed.
  *   """
- *   cdef string fst_type_string = b"" if fst_type is None else tostring(fst_type)             # <<<<<<<<<<<<<<
+ *   cdef string fst_type_string = tostring(fst_type)             # <<<<<<<<<<<<<<
  *   cdef unique_ptr[fst.FstClass] tfst
  *   tfst.reset(fst.Convert(deref(ifst._fst), fst_type_string))
  */
-  __pyx_t_2 = (__pyx_v_fst_type == Py_None);
-  if ((__pyx_t_2 != 0)) {
-    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_kp_b__24); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3374, __pyx_L1_error)
-    __pyx_t_1 = __pyx_t_3;
-  } else {
-    __pyx_t_3 = __pyx_f_9pywrapfst_tostring(__pyx_v_fst_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3374, __pyx_L1_error)
-    __pyx_t_4 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3374, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = __pyx_convert_string_from_py_std__in_string(__pyx_t_4); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3374, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_t_1 = __pyx_t_3;
-  }
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_fst_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3392, __pyx_L1_error)
   __pyx_v_fst_type_string = __pyx_t_1;
 
-  /* "pywrapfst.pyx":3376
- *   cdef string fst_type_string = b"" if fst_type is None else tostring(fst_type)
+  /* "pywrapfst.pyx":3394
+ *   cdef string fst_type_string = tostring(fst_type)
  *   cdef unique_ptr[fst.FstClass] tfst
  *   tfst.reset(fst.Convert(deref(ifst._fst), fst_type_string))             # <<<<<<<<<<<<<<
  *   # Script-land Convert returns a null pointer to signal failure.
@@ -36747,11 +35923,11 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_convert(struct __pyx
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3376, __pyx_L1_error)
+    __PYX_ERR(0, 3394, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(fst::script::Convert((*__pyx_v_ifst->_fst), __pyx_v_fst_type_string));
 
-  /* "pywrapfst.pyx":3378
+  /* "pywrapfst.pyx":3396
  *   tfst.reset(fst.Convert(deref(ifst._fst), fst_type_string))
  *   # Script-land Convert returns a null pointer to signal failure.
  *   if tfst.get() == NULL:             # <<<<<<<<<<<<<<
@@ -36761,111 +35937,53 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_convert(struct __pyx
   __pyx_t_2 = ((__pyx_v_tfst.get() == NULL) != 0);
   if (unlikely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":3379
+    /* "pywrapfst.pyx":3397
  *   # Script-land Convert returns a null pointer to signal failure.
  *   if tfst.get() == NULL:
  *     raise FstOpError("Conversion to {!r} failed".format(fst_type))             # <<<<<<<<<<<<<<
  *   return _init_XFst(tfst.release())
  * 
  */
-    __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3379, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Conversion_to_r_failed, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3379, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_8 = NULL;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
-      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7);
-      if (likely(__pyx_t_8)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
-        __Pyx_INCREF(__pyx_t_8);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_7, function);
-      }
-    }
-    if (!__pyx_t_8) {
-      __pyx_t_6 = __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_fst_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3379, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_6);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_7)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_fst_type};
-        __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3379, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_GOTREF(__pyx_t_6);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_fst_type};
-        __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3379, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_GOTREF(__pyx_t_6);
-      } else
-      #endif
-      {
-        __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3379, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_9);
-        __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_8); __pyx_t_8 = NULL;
-        __Pyx_INCREF(__pyx_v_fst_type);
-        __Pyx_GIVEREF(__pyx_v_fst_type);
-        PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_v_fst_type);
-        __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_9, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3379, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      }
-    }
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3397, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Conversion_to_r_failed, __pyx_n_s_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3397, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_7 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
-      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5);
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
+      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6);
       if (likely(__pyx_t_7)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
         __Pyx_INCREF(__pyx_t_7);
         __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_5, function);
+        __Pyx_DECREF_SET(__pyx_t_6, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3379, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3379, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3379, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3379, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_9);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_t_6);
-        __pyx_t_6 = 0;
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3379, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+    __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_7, __pyx_v_fst_type) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_v_fst_type);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3397, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __pyx_t_6 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_6)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_6);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
       }
     }
+    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3397, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __PYX_ERR(0, 3379, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __PYX_ERR(0, 3397, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":3378
+    /* "pywrapfst.pyx":3396
  *   tfst.reset(fst.Convert(deref(ifst._fst), fst_type_string))
  *   # Script-land Convert returns a null pointer to signal failure.
  *   if tfst.get() == NULL:             # <<<<<<<<<<<<<<
@@ -36874,7 +35992,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_convert(struct __pyx
  */
   }
 
-  /* "pywrapfst.pyx":3380
+  /* "pywrapfst.pyx":3398
  *   if tfst.get() == NULL:
  *     raise FstOpError("Conversion to {!r} failed".format(fst_type))
  *   return _init_XFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -36882,28 +36000,27 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_convert(struct __pyx
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_4 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3380, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_4);
-  __pyx_t_4 = 0;
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3398, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_3);
+  __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3357
+  /* "pywrapfst.pyx":3375
  * 
  * 
- * cpdef _Fst convert(_Fst ifst, fst_type=None):             # <<<<<<<<<<<<<<
+ * cpdef _Fst convert(_Fst ifst, fst_type=b""):             # <<<<<<<<<<<<<<
  *   """
- *   convert(ifst, fst_type=None)
+ *   convert(ifst, fst_type="")
  */
 
   /* function exit code */
   __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
   __Pyx_AddTraceback("pywrapfst.convert", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -36913,9 +36030,9 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_convert(struct __pyx
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_21convert(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_20convert[] = "\n  convert(ifst, fst_type=None)\n\n  Constructively converts an FST to a new internal representation.\n\n  Args:\n    ifst: The input FST.\n    fst_type: A string indicating the FST type to convert to, or None if\n        no conversion is desired.\n\n  Returns:\n    The input FST converted to the desired FST type.\n\n  Raises:\n    FstOpError: Conversion failed.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_21convert(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_23convert(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_22convert[] = "\n  convert(ifst, fst_type=\"\")\n\n  Constructively converts an FST to a new internal representation.\n\n  Args:\n    ifst: The input FST.\n    fst_type: A string indicating the FST type to convert to, or an empty string\n        if no conversion is desired.\n\n  Returns:\n    The input FST converted to the desired FST type.\n\n  Raises:\n    FstOpError: Conversion failed.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_23convert(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   PyObject *__pyx_v_fst_type = 0;
   PyObject *__pyx_r = 0;
@@ -36924,7 +36041,7 @@ static PyObject *__pyx_pw_9pywrapfst_21convert(PyObject *__pyx_self, PyObject *_
   {
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_ifst,&__pyx_n_s_fst_type,0};
     PyObject* values[2] = {0,0};
-    values[1] = ((PyObject *)Py_None);
+    values[1] = ((PyObject *)__pyx_kp_b__10);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
@@ -36949,7 +36066,7 @@ static PyObject *__pyx_pw_9pywrapfst_21convert(PyObject *__pyx_self, PyObject *_
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convert") < 0)) __PYX_ERR(0, 3357, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "convert") < 0)) __PYX_ERR(0, 3375, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -36965,14 +36082,14 @@ static PyObject *__pyx_pw_9pywrapfst_21convert(PyObject *__pyx_self, PyObject *_
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("convert", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3357, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("convert", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3375, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.convert", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3357, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_20convert(__pyx_self, __pyx_v_ifst, __pyx_v_fst_type);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3375, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_22convert(__pyx_self, __pyx_v_ifst, __pyx_v_fst_type);
 
   /* function exit code */
   goto __pyx_L0;
@@ -36983,7 +36100,7 @@ static PyObject *__pyx_pw_9pywrapfst_21convert(PyObject *__pyx_self, PyObject *_
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_20convert(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, PyObject *__pyx_v_fst_type) {
+static PyObject *__pyx_pf_9pywrapfst_22convert(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, PyObject *__pyx_v_fst_type) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -36992,7 +36109,7 @@ static PyObject *__pyx_pf_9pywrapfst_20convert(CYTHON_UNUSED PyObject *__pyx_sel
   __Pyx_XDECREF(__pyx_r);
   __pyx_t_2.__pyx_n = 1;
   __pyx_t_2.fst_type = __pyx_v_fst_type;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_convert(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3357, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_convert(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3375, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -37009,7 +36126,7 @@ static PyObject *__pyx_pf_9pywrapfst_20convert(CYTHON_UNUSED PyObject *__pyx_sel
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3383
+/* "pywrapfst.pyx":3401
  * 
  * 
  * cpdef _MutableFst determinize(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -37017,14 +36134,14 @@ static PyObject *__pyx_pf_9pywrapfst_20convert(CYTHON_UNUSED PyObject *__pyx_sel
  *                               det_type=b"functional",
  */
 
-static PyObject *__pyx_pw_9pywrapfst_23determinize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_25determinize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_determinize *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__69;
+  float __pyx_v_delta = __pyx_k__33;
   PyObject *__pyx_v_det_type = ((PyObject *)__pyx_n_b_functional);
-  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__70;
+  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__34;
   __pyx_t_10basictypes_int64 __pyx_v_subsequential_label = ((__pyx_t_10basictypes_int64)0);
 
-  /* "pywrapfst.pyx":3388
+  /* "pywrapfst.pyx":3406
  *                               int64 nstate=fst.kNoStateId,
  *                               int64 subsequential_label=0,
  *                               weight=None,             # <<<<<<<<<<<<<<
@@ -37033,7 +36150,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
  */
   PyObject *__pyx_v_weight = ((PyObject *)Py_None);
 
-  /* "pywrapfst.pyx":3389
+  /* "pywrapfst.pyx":3407
  *                               int64 subsequential_label=0,
  *                               weight=None,
  *                               bool increment_subsequential_label=False):             # <<<<<<<<<<<<<<
@@ -37055,7 +36172,6 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
   PyObject *__pyx_t_8 = NULL;
-  PyObject *__pyx_t_9 = NULL;
   __Pyx_RefNannySetupContext("determinize", 0);
   if (__pyx_optional_args) {
     if (__pyx_optional_args->__pyx_n > 0) {
@@ -37078,7 +36194,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
     }
   }
 
-  /* "pywrapfst.pyx":3425
+  /* "pywrapfst.pyx":3443
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -37087,11 +36203,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3425, __pyx_L1_error)
+    __PYX_ERR(0, 3443, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":3427
+  /* "pywrapfst.pyx":3445
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   # Threshold is set to semiring Zero (no pruning) if weight unspecified.
  *   cdef fst.WeightClass wc = _get_WeightClass_or_Zero(ifst.weight_type(),             # <<<<<<<<<<<<<<
@@ -37100,29 +36216,29 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-    __PYX_ERR(0, 3427, __pyx_L1_error)
+    __PYX_ERR(0, 3445, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":3428
+  /* "pywrapfst.pyx":3446
  *   # Threshold is set to semiring Zero (no pruning) if weight unspecified.
  *   cdef fst.WeightClass wc = _get_WeightClass_or_Zero(ifst.weight_type(),
  *                                                      weight)             # <<<<<<<<<<<<<<
  *   cdef fst.DeterminizeType determinize_type_enum
  *   if not fst.GetDeterminizeType(tostring(det_type),
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3427, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3445, __pyx_L1_error)
   __pyx_v_wc = __pyx_t_1;
 
-  /* "pywrapfst.pyx":3430
+  /* "pywrapfst.pyx":3448
  *                                                      weight)
  *   cdef fst.DeterminizeType determinize_type_enum
  *   if not fst.GetDeterminizeType(tostring(det_type),             # <<<<<<<<<<<<<<
  *                                 addr(determinize_type_enum)):
  *     raise FstArgError("Unknown determinization type: {!r}".format(det_type))
  */
-  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_det_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3430, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_det_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3448, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":3431
+  /* "pywrapfst.pyx":3449
  *   cdef fst.DeterminizeType determinize_type_enum
  *   if not fst.GetDeterminizeType(tostring(det_type),
  *                                 addr(determinize_type_enum)):             # <<<<<<<<<<<<<<
@@ -37131,7 +36247,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
  */
   __pyx_t_3 = ((!(fst::script::GetDeterminizeType(__pyx_t_2, (&__pyx_v_determinize_type_enum)) != 0)) != 0);
 
-  /* "pywrapfst.pyx":3430
+  /* "pywrapfst.pyx":3448
  *                                                      weight)
  *   cdef fst.DeterminizeType determinize_type_enum
  *   if not fst.GetDeterminizeType(tostring(det_type),             # <<<<<<<<<<<<<<
@@ -37140,16 +36256,16 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
  */
   if (unlikely(__pyx_t_3)) {
 
-    /* "pywrapfst.pyx":3432
+    /* "pywrapfst.pyx":3450
  *   if not fst.GetDeterminizeType(tostring(det_type),
  *                                 addr(determinize_type_enum)):
  *     raise FstArgError("Unknown determinization type: {!r}".format(det_type))             # <<<<<<<<<<<<<<
  *   cdef unique_ptr[fst.DeterminizeOptions] opts
  *   opts.reset(new fst.DeterminizeOptions(delta, wc, nstate, subsequential_label,
  */
-    __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3432, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3450, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Unknown_determinization_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3432, __pyx_L1_error)
+    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Unknown_determinization_type_r, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3450, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_7);
     __pyx_t_8 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
@@ -37161,38 +36277,10 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
         __Pyx_DECREF_SET(__pyx_t_7, function);
       }
     }
-    if (!__pyx_t_8) {
-      __pyx_t_6 = __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_det_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3432, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_6);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_7)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_det_type};
-        __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3432, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_GOTREF(__pyx_t_6);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_det_type};
-        __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3432, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_GOTREF(__pyx_t_6);
-      } else
-      #endif
-      {
-        __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3432, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_9);
-        __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_8); __pyx_t_8 = NULL;
-        __Pyx_INCREF(__pyx_v_det_type);
-        __Pyx_GIVEREF(__pyx_v_det_type);
-        PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_v_det_type);
-        __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_9, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3432, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      }
-    }
+    __pyx_t_6 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_det_type) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_det_type);
+    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3450, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
@@ -37204,47 +36292,17 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
         __Pyx_DECREF_SET(__pyx_t_5, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3432, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3432, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3432, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3432, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_9);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_t_6);
-        __pyx_t_6 = 0;
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3432, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      }
-    }
+    __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3450, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __PYX_ERR(0, 3432, __pyx_L1_error)
+    __PYX_ERR(0, 3450, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":3430
+    /* "pywrapfst.pyx":3448
  *                                                      weight)
  *   cdef fst.DeterminizeType determinize_type_enum
  *   if not fst.GetDeterminizeType(tostring(det_type),             # <<<<<<<<<<<<<<
@@ -37253,7 +36311,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
  */
   }
 
-  /* "pywrapfst.pyx":3434
+  /* "pywrapfst.pyx":3452
  *     raise FstArgError("Unknown determinization type: {!r}".format(det_type))
  *   cdef unique_ptr[fst.DeterminizeOptions] opts
  *   opts.reset(new fst.DeterminizeOptions(delta, wc, nstate, subsequential_label,             # <<<<<<<<<<<<<<
@@ -37262,7 +36320,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
  */
   __pyx_v_opts.reset(new fst::script::DeterminizeOptions(__pyx_v_delta, __pyx_v_wc, __pyx_v_nstate, __pyx_v_subsequential_label, __pyx_v_determinize_type_enum, __pyx_v_increment_subsequential_label));
 
-  /* "pywrapfst.pyx":3437
+  /* "pywrapfst.pyx":3455
  *                                         determinize_type_enum,
  *                                         increment_subsequential_label))
  *   fst.Determinize(deref(ifst._fst), tfst.get(), deref(opts))             # <<<<<<<<<<<<<<
@@ -37271,11 +36329,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3437, __pyx_L1_error)
+    __PYX_ERR(0, 3455, __pyx_L1_error)
   }
   fst::script::Determinize((*__pyx_v_ifst->_fst), __pyx_v_tfst.get(), (*__pyx_v_opts));
 
-  /* "pywrapfst.pyx":3438
+  /* "pywrapfst.pyx":3456
  *                                         increment_subsequential_label))
  *   fst.Determinize(deref(ifst._fst), tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -37283,13 +36341,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_4 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3438, __pyx_L1_error)
+  __pyx_t_4 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3456, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_4);
   __pyx_t_4 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3383
+  /* "pywrapfst.pyx":3401
  * 
  * 
  * cpdef _MutableFst determinize(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -37304,7 +36362,6 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
   __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
   __Pyx_AddTraceback("pywrapfst.determinize", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -37314,9 +36371,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_determinize(s
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_23determinize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_22determinize[] = "\n  determinize(ifst, delta=1e-6, det_type=\"functional\",\n              nstate=NO_STATE_ID, subsequential_label=0, weight=None,\n              incremental_subsequential_label=False)\n\n  Constructively determinizes a weighted FST.\n\n  This operations creates an equivalent FST that has the property that no\n  state has two transitions with the same input label. For this algorithm,\n  epsilon transitions are treated as regular symbols (cf. `rmepsilon`).\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    det_type: Type of determinization; one of: \"functional\" (input transducer is\n        functional), \"nonfunctional\" (input transducer is not functional) and\n        disambiguate\" (input transducer is not functional but only keep the min\n        of ambiguous outputs).\n    nstate: State number threshold.\n    subsequential_label: Input label of arc corresponding to residual final\n        output when producing a subsequential transducer.\n    weight: A Weight or weight string indicating the desired weight threshold\n        below which paths are pruned; if omitted, no paths are pruned.\n    increment_subsequential_label: Increment subsequential when creating\n        several arcs for the residual final output at a given state.\n\n  Returns:\n    An equivalent deterministic FST.\n\n  Raises:\n    FstArgError: Unknown determinization type.\n\n  See also: `disambiguate`, `rmepsilon`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_23determinize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_25determinize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_24determinize[] = "\n  determinize(ifst, delta=1e-6, det_type=\"functional\",\n              nstate=NO_STATE_ID, subsequential_label=0, weight=None,\n              incremental_subsequential_label=False)\n\n  Constructively determinizes a weighted FST.\n\n  This operations creates an equivalent FST that has the property that no\n  state has two transitions with the same input label. For this algorithm,\n  epsilon transitions are treated as regular symbols (cf. `rmepsilon`).\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    det_type: Type of determinization; one of: \"functional\" (input transducer is\n        functional), \"nonfunctional\" (input transducer is not functional) and\n        disambiguate\" (input transducer is not functional but only keep the min\n        of ambiguous outputs).\n    nstate: State number threshold.\n    subsequential_label: Input label of arc corresponding to residual final\n        output when producing a subsequential transducer.\n    weight: A Weight or weight string indicating the desired weight threshold\n        below which paths are pruned; if omitted, no paths are pruned.\n    increment_subsequential_label: Increment subsequential when creating\n        several arcs for the residual final output at a given state.\n\n  Returns:\n    An equivalent deterministic FST.\n\n  Raises:\n    FstArgError: Unknown determinization type.\n\n  See also: `disambiguate`, `rmepsilon`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_25determinize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   float __pyx_v_delta;
   PyObject *__pyx_v_det_type = 0;
@@ -37332,7 +36389,7 @@ static PyObject *__pyx_pw_9pywrapfst_23determinize(PyObject *__pyx_self, PyObjec
     PyObject* values[7] = {0,0,0,0,0,0,0};
     values[2] = ((PyObject *)__pyx_n_b_functional);
 
-    /* "pywrapfst.pyx":3388
+    /* "pywrapfst.pyx":3406
  *                               int64 nstate=fst.kNoStateId,
  *                               int64 subsequential_label=0,
  *                               weight=None,             # <<<<<<<<<<<<<<
@@ -37404,7 +36461,7 @@ static PyObject *__pyx_pw_9pywrapfst_23determinize(PyObject *__pyx_self, PyObjec
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "determinize") < 0)) __PYX_ERR(0, 3383, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "determinize") < 0)) __PYX_ERR(0, 3401, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -37427,27 +36484,27 @@ static PyObject *__pyx_pw_9pywrapfst_23determinize(PyObject *__pyx_self, PyObjec
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3384, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3402, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__69;
+      __pyx_v_delta = __pyx_k__33;
     }
     __pyx_v_det_type = values[2];
     if (values[3]) {
-      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3386, __pyx_L3_error)
+      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3404, __pyx_L3_error)
     } else {
-      __pyx_v_nstate = __pyx_k__70;
+      __pyx_v_nstate = __pyx_k__34;
     }
     if (values[4]) {
-      __pyx_v_subsequential_label = __Pyx_PyInt_As_int64_t(values[4]); if (unlikely((__pyx_v_subsequential_label == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3387, __pyx_L3_error)
+      __pyx_v_subsequential_label = __Pyx_PyInt_As_int64_t(values[4]); if (unlikely((__pyx_v_subsequential_label == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3405, __pyx_L3_error)
     } else {
       __pyx_v_subsequential_label = ((__pyx_t_10basictypes_int64)0);
     }
     __pyx_v_weight = values[5];
     if (values[6]) {
-      __pyx_v_increment_subsequential_label = __Pyx_PyObject_IsTrue(values[6]); if (unlikely((__pyx_v_increment_subsequential_label == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3389, __pyx_L3_error)
+      __pyx_v_increment_subsequential_label = __Pyx_PyObject_IsTrue(values[6]); if (unlikely((__pyx_v_increment_subsequential_label == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3407, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3389
+      /* "pywrapfst.pyx":3407
  *                               int64 subsequential_label=0,
  *                               weight=None,
  *                               bool increment_subsequential_label=False):             # <<<<<<<<<<<<<<
@@ -37459,16 +36516,16 @@ static PyObject *__pyx_pw_9pywrapfst_23determinize(PyObject *__pyx_self, PyObjec
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("determinize", 0, 1, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3383, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("determinize", 0, 1, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3401, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.determinize", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3383, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_22determinize(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_det_type, __pyx_v_nstate, __pyx_v_subsequential_label, __pyx_v_weight, __pyx_v_increment_subsequential_label);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3401, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_24determinize(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_det_type, __pyx_v_nstate, __pyx_v_subsequential_label, __pyx_v_weight, __pyx_v_increment_subsequential_label);
 
-  /* "pywrapfst.pyx":3383
+  /* "pywrapfst.pyx":3401
  * 
  * 
  * cpdef _MutableFst determinize(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -37485,7 +36542,7 @@ static PyObject *__pyx_pw_9pywrapfst_23determinize(PyObject *__pyx_self, PyObjec
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_22determinize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, PyObject *__pyx_v_det_type, __pyx_t_10basictypes_int64 __pyx_v_nstate, __pyx_t_10basictypes_int64 __pyx_v_subsequential_label, PyObject *__pyx_v_weight, bool __pyx_v_increment_subsequential_label) {
+static PyObject *__pyx_pf_9pywrapfst_24determinize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, PyObject *__pyx_v_det_type, __pyx_t_10basictypes_int64 __pyx_v_nstate, __pyx_t_10basictypes_int64 __pyx_v_subsequential_label, PyObject *__pyx_v_weight, bool __pyx_v_increment_subsequential_label) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -37499,7 +36556,7 @@ static PyObject *__pyx_pf_9pywrapfst_22determinize(CYTHON_UNUSED PyObject *__pyx
   __pyx_t_2.subsequential_label = __pyx_v_subsequential_label;
   __pyx_t_2.weight = __pyx_v_weight;
   __pyx_t_2.increment_subsequential_label = __pyx_v_increment_subsequential_label;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_determinize(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3383, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_determinize(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3401, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -37516,7 +36573,7 @@ static PyObject *__pyx_pf_9pywrapfst_22determinize(CYTHON_UNUSED PyObject *__pyx
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3441
+/* "pywrapfst.pyx":3459
  * 
  * 
  * cpdef _MutableFst difference(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -37524,11 +36581,11 @@ static PyObject *__pyx_pf_9pywrapfst_22determinize(CYTHON_UNUSED PyObject *__pyx
  *                              compose_filter=b"auto",
  */
 
-static PyObject *__pyx_pw_9pywrapfst_25difference(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_27difference(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_difference(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_difference *__pyx_optional_args) {
   PyObject *__pyx_v_compose_filter = ((PyObject *)__pyx_n_b_auto);
 
-  /* "pywrapfst.pyx":3444
+  /* "pywrapfst.pyx":3462
  *                              _Fst ifst2,
  *                              compose_filter=b"auto",
  *                              bool connect=True):             # <<<<<<<<<<<<<<
@@ -37553,7 +36610,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_difference(st
     }
   }
 
-  /* "pywrapfst.pyx":3468
+  /* "pywrapfst.pyx":3486
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst1.arc_type()))             # <<<<<<<<<<<<<<
@@ -37562,30 +36619,30 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_difference(st
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3468, __pyx_L1_error)
+    __PYX_ERR(0, 3486, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst1->__pyx_vtab)->arc_type(__pyx_v_ifst1, 0)));
 
-  /* "pywrapfst.pyx":3471
+  /* "pywrapfst.pyx":3489
  *   cdef unique_ptr[fst.ComposeOptions] opts
  *   opts.reset(new fst.ComposeOptions(connect, _get_compose_filter(
  *       tostring(compose_filter))))             # <<<<<<<<<<<<<<
  *   fst.Difference(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_compose_filter, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3471, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_compose_filter, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3489, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":3470
+  /* "pywrapfst.pyx":3488
  *   tfst.reset(new fst.VectorFstClass(ifst1.arc_type()))
  *   cdef unique_ptr[fst.ComposeOptions] opts
  *   opts.reset(new fst.ComposeOptions(connect, _get_compose_filter(             # <<<<<<<<<<<<<<
  *       tostring(compose_filter))))
  *   fst.Difference(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))
  */
-  __pyx_t_2 = __pyx_f_9pywrapfst__get_compose_filter(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3470, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst__get_compose_filter(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3488, __pyx_L1_error)
   __pyx_v_opts.reset(new fst::ComposeOptions(__pyx_v_connect, __pyx_t_2));
 
-  /* "pywrapfst.pyx":3472
+  /* "pywrapfst.pyx":3490
  *   opts.reset(new fst.ComposeOptions(connect, _get_compose_filter(
  *       tostring(compose_filter))))
  *   fst.Difference(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))             # <<<<<<<<<<<<<<
@@ -37594,15 +36651,15 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_difference(st
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3472, __pyx_L1_error)
+    __PYX_ERR(0, 3490, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst2) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3472, __pyx_L1_error)
+    __PYX_ERR(0, 3490, __pyx_L1_error)
   }
   fst::script::Difference((*__pyx_v_ifst1->_fst), (*__pyx_v_ifst2->_fst), __pyx_v_tfst.get(), (*__pyx_v_opts));
 
-  /* "pywrapfst.pyx":3473
+  /* "pywrapfst.pyx":3491
  *       tostring(compose_filter))))
  *   fst.Difference(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -37610,13 +36667,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_difference(st
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3473, __pyx_L1_error)
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3491, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_3);
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3441
+  /* "pywrapfst.pyx":3459
  * 
  * 
  * cpdef _MutableFst difference(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -37636,9 +36693,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_difference(st
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_25difference(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_24difference[] = "\n  difference(ifst1, ifst2, compose_filter=\"auto\", connect=True)\n\n  Constructively computes the difference of two FSTs.\n\n  This operation computes the difference between two FSAs. Only strings that are\n  in the first automaton but not in second are retained in the result. The first\n  argument must be an acceptor; the second argument must be an unweighted,\n  epsilon-free, deterministic acceptor. The output labels of the first\n  transducer or the input labels of the second transducer must be sorted (or\n  otherwise support appropriate matchers).\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    compose_filter: A string matching a known composition filter; one of:\n        \"alt_sequence\", \"auto\", \"match\", \"null\", \"sequence\", \"trivial\".\n    connect: Should the output FST be trimmed?\n\n  Returns:\n    An FST representing the difference of the FSTs.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_25difference(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_27difference(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_26difference[] = "\n  difference(ifst1, ifst2, compose_filter=\"auto\", connect=True)\n\n  Constructively computes the difference of two FSTs.\n\n  This operation computes the difference between two FSAs. Only strings that are\n  in the first automaton but not in second are retained in the result. The first\n  argument must be an acceptor; the second argument must be an unweighted,\n  epsilon-free, deterministic acceptor. The output labels of the first\n  transducer or the input labels of the second transducer must be sorted (or\n  otherwise support appropriate matchers).\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    compose_filter: A string matching a known composition filter; one of:\n        \"alt_sequence\", \"auto\", \"match\", \"null\", \"sequence\", \"trivial\".\n    connect: Should the output FST be trimmed?\n\n  Returns:\n    An FST representing the difference of the FSTs.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_27difference(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1 = 0;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2 = 0;
   PyObject *__pyx_v_compose_filter = 0;
@@ -37674,7 +36731,7 @@ static PyObject *__pyx_pw_9pywrapfst_25difference(PyObject *__pyx_self, PyObject
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ifst2)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("difference", 0, 2, 4, 1); __PYX_ERR(0, 3441, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("difference", 0, 2, 4, 1); __PYX_ERR(0, 3459, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
@@ -37690,7 +36747,7 @@ static PyObject *__pyx_pw_9pywrapfst_25difference(PyObject *__pyx_self, PyObject
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "difference") < 0)) __PYX_ERR(0, 3441, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "difference") < 0)) __PYX_ERR(0, 3459, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -37708,10 +36765,10 @@ static PyObject *__pyx_pw_9pywrapfst_25difference(PyObject *__pyx_self, PyObject
     __pyx_v_ifst2 = ((struct __pyx_obj_9pywrapfst__Fst *)values[1]);
     __pyx_v_compose_filter = values[2];
     if (values[3]) {
-      __pyx_v_connect = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_connect == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3444, __pyx_L3_error)
+      __pyx_v_connect = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_connect == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3462, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3444
+      /* "pywrapfst.pyx":3462
  *                              _Fst ifst2,
  *                              compose_filter=b"auto",
  *                              bool connect=True):             # <<<<<<<<<<<<<<
@@ -37723,17 +36780,17 @@ static PyObject *__pyx_pw_9pywrapfst_25difference(PyObject *__pyx_self, PyObject
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("difference", 0, 2, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3441, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("difference", 0, 2, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3459, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.difference", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3441, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3442, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_24difference(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_compose_filter, __pyx_v_connect);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3459, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3460, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_26difference(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_compose_filter, __pyx_v_connect);
 
-  /* "pywrapfst.pyx":3441
+  /* "pywrapfst.pyx":3459
  * 
  * 
  * cpdef _MutableFst difference(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -37750,7 +36807,7 @@ static PyObject *__pyx_pw_9pywrapfst_25difference(PyObject *__pyx_self, PyObject
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_24difference(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect) {
+static PyObject *__pyx_pf_9pywrapfst_26difference(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -37760,7 +36817,7 @@ static PyObject *__pyx_pf_9pywrapfst_24difference(CYTHON_UNUSED PyObject *__pyx_
   __pyx_t_2.__pyx_n = 2;
   __pyx_t_2.compose_filter = __pyx_v_compose_filter;
   __pyx_t_2.connect = __pyx_v_connect;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_difference(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3441, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_difference(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3459, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -37777,7 +36834,7 @@ static PyObject *__pyx_pf_9pywrapfst_24difference(CYTHON_UNUSED PyObject *__pyx_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3476
+/* "pywrapfst.pyx":3494
  * 
  * 
  * cpdef _MutableFst disambiguate(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -37785,13 +36842,13 @@ static PyObject *__pyx_pf_9pywrapfst_24difference(CYTHON_UNUSED PyObject *__pyx_
  *                                int64 nstate=fst.kNoStateId,
  */
 
-static PyObject *__pyx_pw_9pywrapfst_27disambiguate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_29disambiguate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_disambiguate(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_disambiguate *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__71;
-  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__72;
+  float __pyx_v_delta = __pyx_k__35;
+  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__36;
   __pyx_t_10basictypes_int64 __pyx_v_subsequential_label = ((__pyx_t_10basictypes_int64)0);
 
-  /* "pywrapfst.pyx":3480
+  /* "pywrapfst.pyx":3498
  *                                int64 nstate=fst.kNoStateId,
  *                                int64 subsequential_label=0,
  *                                weight=None):             # <<<<<<<<<<<<<<
@@ -37822,7 +36879,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_disambiguate(
     }
   }
 
-  /* "pywrapfst.pyx":3507
+  /* "pywrapfst.pyx":3525
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -37831,11 +36888,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_disambiguate(
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3507, __pyx_L1_error)
+    __PYX_ERR(0, 3525, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":3509
+  /* "pywrapfst.pyx":3527
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   # Threshold is set to semiring Zero (no pruning) if no weight is specified.
  *   cdef fst.WeightClass wc = _get_WeightClass_or_Zero(ifst.weight_type(),             # <<<<<<<<<<<<<<
@@ -37844,20 +36901,20 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_disambiguate(
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-    __PYX_ERR(0, 3509, __pyx_L1_error)
+    __PYX_ERR(0, 3527, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":3510
+  /* "pywrapfst.pyx":3528
  *   # Threshold is set to semiring Zero (no pruning) if no weight is specified.
  *   cdef fst.WeightClass wc = _get_WeightClass_or_Zero(ifst.weight_type(),
  *                                                      weight)             # <<<<<<<<<<<<<<
  *   cdef unique_ptr[fst.DisambiguateOptions] opts
  *   opts.reset(new fst.DisambiguateOptions(delta, wc, nstate,
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3509, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3527, __pyx_L1_error)
   __pyx_v_wc = __pyx_t_1;
 
-  /* "pywrapfst.pyx":3512
+  /* "pywrapfst.pyx":3530
  *                                                      weight)
  *   cdef unique_ptr[fst.DisambiguateOptions] opts
  *   opts.reset(new fst.DisambiguateOptions(delta, wc, nstate,             # <<<<<<<<<<<<<<
@@ -37866,7 +36923,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_disambiguate(
  */
   __pyx_v_opts.reset(new fst::script::DisambiguateOptions(__pyx_v_delta, __pyx_v_wc, __pyx_v_nstate, __pyx_v_subsequential_label));
 
-  /* "pywrapfst.pyx":3514
+  /* "pywrapfst.pyx":3532
  *   opts.reset(new fst.DisambiguateOptions(delta, wc, nstate,
  *                                          subsequential_label))
  *   fst.Disambiguate(deref(ifst._fst), tfst.get(), deref(opts))             # <<<<<<<<<<<<<<
@@ -37875,11 +36932,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_disambiguate(
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3514, __pyx_L1_error)
+    __PYX_ERR(0, 3532, __pyx_L1_error)
   }
   fst::script::Disambiguate((*__pyx_v_ifst->_fst), __pyx_v_tfst.get(), (*__pyx_v_opts));
 
-  /* "pywrapfst.pyx":3515
+  /* "pywrapfst.pyx":3533
  *                                          subsequential_label))
  *   fst.Disambiguate(deref(ifst._fst), tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -37887,13 +36944,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_disambiguate(
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3515, __pyx_L1_error)
+  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3533, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_2);
   __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3476
+  /* "pywrapfst.pyx":3494
  * 
  * 
  * cpdef _MutableFst disambiguate(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -37913,9 +36970,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_disambiguate(
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_27disambiguate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_26disambiguate[] = "\n  disambiguate(ifst, delta=0.0009765625, nstate=NO_STATE_ID,\n               subsequential_label=0, weight=None):\n\n  Constructively disambiguates a weighted transducer.\n\n  This operation disambiguates a weighted transducer. The result will be an\n  equivalent FST that has the property that no two successful paths have the\n  same input labeling. For this algorithm, epsilon transitions are treated as\n  regular symbols (cf. `rmepsilon`).\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    nstate: State number threshold.\n    subsequential_label: Input label of arc corresponding to residual final\n        output when producing a subsequential transducer.\n    weight: A Weight or weight string indicating the desired weight threshold\n        below which paths are pruned; if omitted, no paths are pruned.\n\n  Returns:\n    An equivalent disambiguated FST.\n\n  See also: `determinize`, `rmepsilon`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_27disambiguate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_29disambiguate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_28disambiguate[] = "\n  disambiguate(ifst, delta=0.0009765625, nstate=NO_STATE_ID,\n               subsequential_label=0, weight=None):\n\n  Constructively disambiguates a weighted transducer.\n\n  This operation disambiguates a weighted transducer. The result will be an\n  equivalent FST that has the property that no two successful paths have the\n  same input labeling. For this algorithm, epsilon transitions are treated as\n  regular symbols (cf. `rmepsilon`).\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    nstate: State number threshold.\n    subsequential_label: Input label of arc corresponding to residual final\n        output when producing a subsequential transducer.\n    weight: A Weight or weight string indicating the desired weight threshold\n        below which paths are pruned; if omitted, no paths are pruned.\n\n  Returns:\n    An equivalent disambiguated FST.\n\n  See also: `determinize`, `rmepsilon`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_29disambiguate(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   float __pyx_v_delta;
   __pyx_t_10basictypes_int64 __pyx_v_nstate;
@@ -37928,7 +36985,7 @@ static PyObject *__pyx_pw_9pywrapfst_27disambiguate(PyObject *__pyx_self, PyObje
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_ifst,&__pyx_n_s_delta,&__pyx_n_s_nstate,&__pyx_n_s_subsequential_label,&__pyx_n_s_weight,0};
     PyObject* values[5] = {0,0,0,0,0};
 
-    /* "pywrapfst.pyx":3480
+    /* "pywrapfst.pyx":3498
  *                                int64 nstate=fst.kNoStateId,
  *                                int64 subsequential_label=0,
  *                                weight=None):             # <<<<<<<<<<<<<<
@@ -37984,7 +37041,7 @@ static PyObject *__pyx_pw_9pywrapfst_27disambiguate(PyObject *__pyx_self, PyObje
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "disambiguate") < 0)) __PYX_ERR(0, 3476, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "disambiguate") < 0)) __PYX_ERR(0, 3494, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -38003,17 +37060,17 @@ static PyObject *__pyx_pw_9pywrapfst_27disambiguate(PyObject *__pyx_self, PyObje
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3477, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3495, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__71;
+      __pyx_v_delta = __pyx_k__35;
     }
     if (values[2]) {
-      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[2]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3478, __pyx_L3_error)
+      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[2]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3496, __pyx_L3_error)
     } else {
-      __pyx_v_nstate = __pyx_k__72;
+      __pyx_v_nstate = __pyx_k__36;
     }
     if (values[3]) {
-      __pyx_v_subsequential_label = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_subsequential_label == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3479, __pyx_L3_error)
+      __pyx_v_subsequential_label = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_subsequential_label == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3497, __pyx_L3_error)
     } else {
       __pyx_v_subsequential_label = ((__pyx_t_10basictypes_int64)0);
     }
@@ -38021,16 +37078,16 @@ static PyObject *__pyx_pw_9pywrapfst_27disambiguate(PyObject *__pyx_self, PyObje
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("disambiguate", 0, 1, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3476, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("disambiguate", 0, 1, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3494, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.disambiguate", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3476, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_26disambiguate(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_nstate, __pyx_v_subsequential_label, __pyx_v_weight);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3494, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_28disambiguate(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_nstate, __pyx_v_subsequential_label, __pyx_v_weight);
 
-  /* "pywrapfst.pyx":3476
+  /* "pywrapfst.pyx":3494
  * 
  * 
  * cpdef _MutableFst disambiguate(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -38047,7 +37104,7 @@ static PyObject *__pyx_pw_9pywrapfst_27disambiguate(PyObject *__pyx_self, PyObje
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_26disambiguate(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, __pyx_t_10basictypes_int64 __pyx_v_subsequential_label, PyObject *__pyx_v_weight) {
+static PyObject *__pyx_pf_9pywrapfst_28disambiguate(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, __pyx_t_10basictypes_int64 __pyx_v_subsequential_label, PyObject *__pyx_v_weight) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -38059,7 +37116,7 @@ static PyObject *__pyx_pf_9pywrapfst_26disambiguate(CYTHON_UNUSED PyObject *__py
   __pyx_t_2.nstate = __pyx_v_nstate;
   __pyx_t_2.subsequential_label = __pyx_v_subsequential_label;
   __pyx_t_2.weight = __pyx_v_weight;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_disambiguate(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3476, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_disambiguate(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3494, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -38076,7 +37133,7 @@ static PyObject *__pyx_pf_9pywrapfst_26disambiguate(CYTHON_UNUSED PyObject *__py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3518
+/* "pywrapfst.pyx":3536
  * 
  * 
  * cpdef _MutableFst epsnormalize(_Fst ifst, bool eps_norm_output=False):             # <<<<<<<<<<<<<<
@@ -38084,7 +37141,7 @@ static PyObject *__pyx_pf_9pywrapfst_26disambiguate(CYTHON_UNUSED PyObject *__py
  *   epsnormalize(ifst, eps_norm_output=False)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_29epsnormalize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_31epsnormalize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_epsnormalize *__pyx_optional_args) {
   bool __pyx_v_eps_norm_output = ((bool)0);
   std::unique_ptr<fst::script::VectorFstClass>  __pyx_v_tfst;
@@ -38099,7 +37156,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(
     }
   }
 
-  /* "pywrapfst.pyx":3541
+  /* "pywrapfst.pyx":3559
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -38108,11 +37165,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3541, __pyx_L1_error)
+    __PYX_ERR(0, 3559, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":3542
+  /* "pywrapfst.pyx":3560
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   fst.EpsNormalize(deref(ifst._fst), tfst.get(), fst.EPS_NORM_OUTPUT if             # <<<<<<<<<<<<<<
@@ -38121,10 +37178,10 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3542, __pyx_L1_error)
+    __PYX_ERR(0, 3560, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":3543
+  /* "pywrapfst.pyx":3561
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   fst.EpsNormalize(deref(ifst._fst), tfst.get(), fst.EPS_NORM_OUTPUT if
  *                                                  eps_norm_output else             # <<<<<<<<<<<<<<
@@ -38133,7 +37190,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(
  */
   if ((__pyx_v_eps_norm_output != 0)) {
 
-    /* "pywrapfst.pyx":3542
+    /* "pywrapfst.pyx":3560
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   fst.EpsNormalize(deref(ifst._fst), tfst.get(), fst.EPS_NORM_OUTPUT if             # <<<<<<<<<<<<<<
@@ -38143,7 +37200,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(
     __pyx_t_1 = fst::EPS_NORM_OUTPUT;
   } else {
 
-    /* "pywrapfst.pyx":3544
+    /* "pywrapfst.pyx":3562
  *   fst.EpsNormalize(deref(ifst._fst), tfst.get(), fst.EPS_NORM_OUTPUT if
  *                                                  eps_norm_output else
  *                                                  fst.EPS_NORM_INPUT)             # <<<<<<<<<<<<<<
@@ -38153,7 +37210,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(
     __pyx_t_1 = fst::EPS_NORM_INPUT;
   }
 
-  /* "pywrapfst.pyx":3542
+  /* "pywrapfst.pyx":3560
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   fst.EpsNormalize(deref(ifst._fst), tfst.get(), fst.EPS_NORM_OUTPUT if             # <<<<<<<<<<<<<<
@@ -38162,7 +37219,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(
  */
   fst::script::EpsNormalize((*__pyx_v_ifst->_fst), __pyx_v_tfst.get(), __pyx_t_1);
 
-  /* "pywrapfst.pyx":3545
+  /* "pywrapfst.pyx":3563
  *                                                  eps_norm_output else
  *                                                  fst.EPS_NORM_INPUT)
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -38170,13 +37227,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3545, __pyx_L1_error)
+  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3563, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_2);
   __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3518
+  /* "pywrapfst.pyx":3536
  * 
  * 
  * cpdef _MutableFst epsnormalize(_Fst ifst, bool eps_norm_output=False):             # <<<<<<<<<<<<<<
@@ -38196,9 +37253,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_epsnormalize(
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_29epsnormalize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_28epsnormalize[] = "\n  epsnormalize(ifst, eps_norm_output=False)\n\n  Constructively epsilon-normalizes an FST.\n\n  This operation creates an equivalent FST that is epsilon-normalized. An\n  acceptor is epsilon-normalized if it it is epsilon-removed (cf. `rmepsilon`).\n  A transducer is input epsilon-normalized if, in addition, along any path, all\n  arcs with epsilon input labels follow all arcs with non-epsilon input labels.\n  Output epsilon-normalized is defined similarly. The input FST must be\n  functional.\n\n  Args:\n    ifst: The input FST.\n    eps_norm_output: Should the FST be output epsilon-normalized?\n\n  Returns:\n    An equivalent epsilon-normalized FST.\n\n  See also: `rmepsilon`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_29epsnormalize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_31epsnormalize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_30epsnormalize[] = "\n  epsnormalize(ifst, eps_norm_output=False)\n\n  Constructively epsilon-normalizes an FST.\n\n  This operation creates an equivalent FST that is epsilon-normalized. An\n  acceptor is epsilon-normalized if it it is epsilon-removed (cf. `rmepsilon`).\n  A transducer is input epsilon-normalized if, in addition, along any path, all\n  arcs with epsilon input labels follow all arcs with non-epsilon input labels.\n  Output epsilon-normalized is defined similarly. The input FST must be\n  functional.\n\n  Args:\n    ifst: The input FST.\n    eps_norm_output: Should the FST be output epsilon-normalized?\n\n  Returns:\n    An equivalent epsilon-normalized FST.\n\n  See also: `rmepsilon`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_31epsnormalize(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   bool __pyx_v_eps_norm_output;
   PyObject *__pyx_r = 0;
@@ -38231,7 +37288,7 @@ static PyObject *__pyx_pw_9pywrapfst_29epsnormalize(PyObject *__pyx_self, PyObje
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "epsnormalize") < 0)) __PYX_ERR(0, 3518, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "epsnormalize") < 0)) __PYX_ERR(0, 3536, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -38244,21 +37301,21 @@ static PyObject *__pyx_pw_9pywrapfst_29epsnormalize(PyObject *__pyx_self, PyObje
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_eps_norm_output = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_eps_norm_output == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3518, __pyx_L3_error)
+      __pyx_v_eps_norm_output = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_eps_norm_output == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3536, __pyx_L3_error)
     } else {
       __pyx_v_eps_norm_output = ((bool)0);
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("epsnormalize", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3518, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("epsnormalize", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3536, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.epsnormalize", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3518, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_28epsnormalize(__pyx_self, __pyx_v_ifst, __pyx_v_eps_norm_output);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3536, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_30epsnormalize(__pyx_self, __pyx_v_ifst, __pyx_v_eps_norm_output);
 
   /* function exit code */
   goto __pyx_L0;
@@ -38269,7 +37326,7 @@ static PyObject *__pyx_pw_9pywrapfst_29epsnormalize(PyObject *__pyx_self, PyObje
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_28epsnormalize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, bool __pyx_v_eps_norm_output) {
+static PyObject *__pyx_pf_9pywrapfst_30epsnormalize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, bool __pyx_v_eps_norm_output) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -38278,7 +37335,7 @@ static PyObject *__pyx_pf_9pywrapfst_28epsnormalize(CYTHON_UNUSED PyObject *__py
   __Pyx_XDECREF(__pyx_r);
   __pyx_t_2.__pyx_n = 1;
   __pyx_t_2.eps_norm_output = __pyx_v_eps_norm_output;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_epsnormalize(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3518, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_epsnormalize(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3536, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -38295,7 +37352,7 @@ static PyObject *__pyx_pf_9pywrapfst_28epsnormalize(CYTHON_UNUSED PyObject *__py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3548
+/* "pywrapfst.pyx":3566
  * 
  * 
  * cpdef bool equal(_Fst ifst1, _Fst ifst2, float delta=fst.kDelta):             # <<<<<<<<<<<<<<
@@ -38303,9 +37360,9 @@ static PyObject *__pyx_pf_9pywrapfst_28epsnormalize(CYTHON_UNUSED PyObject *__py
  *   equal(ifst1, ifst2, delta=0.0009765625)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_31equal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_33equal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static bool __pyx_f_9pywrapfst_equal(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_equal *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__73;
+  float __pyx_v_delta = __pyx_k__37;
   bool __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("equal", 0);
@@ -38315,7 +37372,7 @@ static bool __pyx_f_9pywrapfst_equal(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_i
     }
   }
 
-  /* "pywrapfst.pyx":3568
+  /* "pywrapfst.pyx":3586
  *   See also: `equivalent`, `isomorphic`, `randequivalent`.
  *   """
  *   return fst.Equal(deref(ifst1._fst), deref(ifst2._fst), delta)             # <<<<<<<<<<<<<<
@@ -38324,16 +37381,16 @@ static bool __pyx_f_9pywrapfst_equal(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_i
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3568, __pyx_L1_error)
+    __PYX_ERR(0, 3586, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst2) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3568, __pyx_L1_error)
+    __PYX_ERR(0, 3586, __pyx_L1_error)
   }
   __pyx_r = fst::script::Equal((*__pyx_v_ifst1->_fst), (*__pyx_v_ifst2->_fst), __pyx_v_delta);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3548
+  /* "pywrapfst.pyx":3566
  * 
  * 
  * cpdef bool equal(_Fst ifst1, _Fst ifst2, float delta=fst.kDelta):             # <<<<<<<<<<<<<<
@@ -38351,9 +37408,9 @@ static bool __pyx_f_9pywrapfst_equal(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_i
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_31equal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_30equal[] = "\n  equal(ifst1, ifst2, delta=0.0009765625)\n\n  Are two FSTs equal?\n\n  This function tests whether two FSTs have the same states with the same\n  numbering and the same transitions with the same labels and weights in the\n  same order.\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    delta: Comparison/quantization delta.\n\n  Returns:\n    True if the FSTs satisfy the above condition, else False.\n\n  See also: `equivalent`, `isomorphic`, `randequivalent`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_31equal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_33equal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_32equal[] = "\n  equal(ifst1, ifst2, delta=0.0009765625)\n\n  Are two FSTs equal?\n\n  This function tests whether two FSTs have the same states with the same\n  numbering and the same transitions with the same labels and weights in the\n  same order.\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    delta: Comparison/quantization delta.\n\n  Returns:\n    True if the FSTs satisfy the above condition, else False.\n\n  See also: `equivalent`, `isomorphic`, `randequivalent`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_33equal(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1 = 0;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2 = 0;
   float __pyx_v_delta;
@@ -38385,7 +37442,7 @@ static PyObject *__pyx_pw_9pywrapfst_31equal(PyObject *__pyx_self, PyObject *__p
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ifst2)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("equal", 0, 2, 3, 1); __PYX_ERR(0, 3548, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("equal", 0, 2, 3, 1); __PYX_ERR(0, 3566, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
@@ -38395,7 +37452,7 @@ static PyObject *__pyx_pw_9pywrapfst_31equal(PyObject *__pyx_self, PyObject *__p
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "equal") < 0)) __PYX_ERR(0, 3548, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "equal") < 0)) __PYX_ERR(0, 3566, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -38410,22 +37467,22 @@ static PyObject *__pyx_pw_9pywrapfst_31equal(PyObject *__pyx_self, PyObject *__p
     __pyx_v_ifst1 = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     __pyx_v_ifst2 = ((struct __pyx_obj_9pywrapfst__Fst *)values[1]);
     if (values[2]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3548, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3566, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__73;
+      __pyx_v_delta = __pyx_k__37;
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("equal", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3548, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("equal", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3566, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.equal", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3548, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3548, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_30equal(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_delta);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3566, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3566, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_32equal(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_delta);
 
   /* function exit code */
   goto __pyx_L0;
@@ -38436,7 +37493,7 @@ static PyObject *__pyx_pw_9pywrapfst_31equal(PyObject *__pyx_self, PyObject *__p
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_30equal(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta) {
+static PyObject *__pyx_pf_9pywrapfst_32equal(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   bool __pyx_t_1;
@@ -38447,7 +37504,7 @@ static PyObject *__pyx_pf_9pywrapfst_30equal(CYTHON_UNUSED PyObject *__pyx_self,
   __pyx_t_2.__pyx_n = 1;
   __pyx_t_2.delta = __pyx_v_delta;
   __pyx_t_1 = __pyx_f_9pywrapfst_equal(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2); 
-  __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3548, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3566, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
@@ -38464,7 +37521,7 @@ static PyObject *__pyx_pf_9pywrapfst_30equal(CYTHON_UNUSED PyObject *__pyx_self,
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3571
+/* "pywrapfst.pyx":3589
  * 
  * 
  * cpdef bool equivalent(_Fst ifst1, _Fst ifst2, float delta=fst.kDelta) except *:             # <<<<<<<<<<<<<<
@@ -38472,9 +37529,9 @@ static PyObject *__pyx_pf_9pywrapfst_30equal(CYTHON_UNUSED PyObject *__pyx_self,
  *   equivalent(ifst1, ifst2, delta=0.0009765625)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_33equivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_35equivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static bool __pyx_f_9pywrapfst_equivalent(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_equivalent *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__74;
+  float __pyx_v_delta = __pyx_k__38;
   bool __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("equivalent", 0);
@@ -38484,7 +37541,7 @@ static bool __pyx_f_9pywrapfst_equivalent(struct __pyx_obj_9pywrapfst__Fst *__py
     }
   }
 
-  /* "pywrapfst.pyx":3591
+  /* "pywrapfst.pyx":3609
  *   See also: `equal`, `isomorphic`, `randequivalent`.
  *   """
  *   return fst.Equivalent(deref(ifst1._fst), deref(ifst2._fst), delta)             # <<<<<<<<<<<<<<
@@ -38493,16 +37550,16 @@ static bool __pyx_f_9pywrapfst_equivalent(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3591, __pyx_L1_error)
+    __PYX_ERR(0, 3609, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst2) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3591, __pyx_L1_error)
+    __PYX_ERR(0, 3609, __pyx_L1_error)
   }
   __pyx_r = fst::script::Equivalent((*__pyx_v_ifst1->_fst), (*__pyx_v_ifst2->_fst), __pyx_v_delta);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3571
+  /* "pywrapfst.pyx":3589
  * 
  * 
  * cpdef bool equivalent(_Fst ifst1, _Fst ifst2, float delta=fst.kDelta) except *:             # <<<<<<<<<<<<<<
@@ -38520,9 +37577,9 @@ static bool __pyx_f_9pywrapfst_equivalent(struct __pyx_obj_9pywrapfst__Fst *__py
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_33equivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_32equivalent[] = "\n  equivalent(ifst1, ifst2, delta=0.0009765625)\n\n  Are the two acceptors equivalent?\n\n  This operation tests whether two epsilon-free deterministic weighted\n  acceptors are equivalent, that is if they accept the same strings with the\n  same weights.\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    delta: Comparison/quantization delta.\n\n  Returns:\n    True if the FSTs satisfy the above condition, else False.\n\n  See also: `equal`, `isomorphic`, `randequivalent`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_33equivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_35equivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_34equivalent[] = "\n  equivalent(ifst1, ifst2, delta=0.0009765625)\n\n  Are the two acceptors equivalent?\n\n  This operation tests whether two epsilon-free deterministic weighted\n  acceptors are equivalent, that is if they accept the same strings with the\n  same weights.\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    delta: Comparison/quantization delta.\n\n  Returns:\n    True if the FSTs satisfy the above condition, else False.\n\n  See also: `equal`, `isomorphic`, `randequivalent`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_35equivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1 = 0;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2 = 0;
   float __pyx_v_delta;
@@ -38554,7 +37611,7 @@ static PyObject *__pyx_pw_9pywrapfst_33equivalent(PyObject *__pyx_self, PyObject
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ifst2)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("equivalent", 0, 2, 3, 1); __PYX_ERR(0, 3571, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("equivalent", 0, 2, 3, 1); __PYX_ERR(0, 3589, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
@@ -38564,7 +37621,7 @@ static PyObject *__pyx_pw_9pywrapfst_33equivalent(PyObject *__pyx_self, PyObject
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "equivalent") < 0)) __PYX_ERR(0, 3571, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "equivalent") < 0)) __PYX_ERR(0, 3589, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -38579,22 +37636,22 @@ static PyObject *__pyx_pw_9pywrapfst_33equivalent(PyObject *__pyx_self, PyObject
     __pyx_v_ifst1 = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     __pyx_v_ifst2 = ((struct __pyx_obj_9pywrapfst__Fst *)values[1]);
     if (values[2]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3571, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3589, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__74;
+      __pyx_v_delta = __pyx_k__38;
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("equivalent", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3571, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("equivalent", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3589, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.equivalent", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3571, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3571, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_32equivalent(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_delta);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3589, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3589, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_34equivalent(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_delta);
 
   /* function exit code */
   goto __pyx_L0;
@@ -38605,7 +37662,7 @@ static PyObject *__pyx_pw_9pywrapfst_33equivalent(PyObject *__pyx_self, PyObject
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_32equivalent(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta) {
+static PyObject *__pyx_pf_9pywrapfst_34equivalent(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   bool __pyx_t_1;
@@ -38615,8 +37672,8 @@ static PyObject *__pyx_pf_9pywrapfst_32equivalent(CYTHON_UNUSED PyObject *__pyx_
   __Pyx_XDECREF(__pyx_r);
   __pyx_t_2.__pyx_n = 1;
   __pyx_t_2.delta = __pyx_v_delta;
-  __pyx_t_1 = __pyx_f_9pywrapfst_equivalent(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2); if (unlikely(__pyx_t_1 == ((bool)-1) && PyErr_Occurred())) __PYX_ERR(0, 3571, __pyx_L1_error)
-  __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3571, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_equivalent(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2); if (unlikely(__pyx_t_1 == ((bool)-1) && PyErr_Occurred())) __PYX_ERR(0, 3589, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3589, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
@@ -38633,7 +37690,7 @@ static PyObject *__pyx_pf_9pywrapfst_32equivalent(CYTHON_UNUSED PyObject *__pyx_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3594
+/* "pywrapfst.pyx":3612
  * 
  * 
  * cpdef _MutableFst intersect(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -38641,11 +37698,11 @@ static PyObject *__pyx_pf_9pywrapfst_32equivalent(CYTHON_UNUSED PyObject *__pyx_
  *                             compose_filter=b"auto",
  */
 
-static PyObject *__pyx_pw_9pywrapfst_35intersect(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_37intersect(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_intersect(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_intersect *__pyx_optional_args) {
   PyObject *__pyx_v_compose_filter = ((PyObject *)__pyx_n_b_auto);
 
-  /* "pywrapfst.pyx":3597
+  /* "pywrapfst.pyx":3615
  *                             _Fst ifst2,
  *                             compose_filter=b"auto",
  *                             bool connect=True):             # <<<<<<<<<<<<<<
@@ -38670,7 +37727,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_intersect(str
     }
   }
 
-  /* "pywrapfst.pyx":3619
+  /* "pywrapfst.pyx":3637
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst1.arc_type()))             # <<<<<<<<<<<<<<
@@ -38679,21 +37736,21 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_intersect(str
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3619, __pyx_L1_error)
+    __PYX_ERR(0, 3637, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst1->__pyx_vtab)->arc_type(__pyx_v_ifst1, 0)));
 
-  /* "pywrapfst.pyx":3622
+  /* "pywrapfst.pyx":3640
  *   cdef unique_ptr[fst.ComposeOptions] opts
  *   opts.reset(new fst.ComposeOptions(connect,
  *         _get_compose_filter(tostring(compose_filter))))             # <<<<<<<<<<<<<<
  *   fst.Intersect(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_compose_filter, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3622, __pyx_L1_error)
-  __pyx_t_2 = __pyx_f_9pywrapfst__get_compose_filter(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3622, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_compose_filter, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3640, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst__get_compose_filter(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3640, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":3621
+  /* "pywrapfst.pyx":3639
  *   tfst.reset(new fst.VectorFstClass(ifst1.arc_type()))
  *   cdef unique_ptr[fst.ComposeOptions] opts
  *   opts.reset(new fst.ComposeOptions(connect,             # <<<<<<<<<<<<<<
@@ -38702,7 +37759,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_intersect(str
  */
   __pyx_v_opts.reset(new fst::ComposeOptions(__pyx_v_connect, __pyx_t_2));
 
-  /* "pywrapfst.pyx":3623
+  /* "pywrapfst.pyx":3641
  *   opts.reset(new fst.ComposeOptions(connect,
  *         _get_compose_filter(tostring(compose_filter))))
  *   fst.Intersect(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))             # <<<<<<<<<<<<<<
@@ -38711,15 +37768,15 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_intersect(str
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3623, __pyx_L1_error)
+    __PYX_ERR(0, 3641, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst2) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3623, __pyx_L1_error)
+    __PYX_ERR(0, 3641, __pyx_L1_error)
   }
   fst::script::Intersect((*__pyx_v_ifst1->_fst), (*__pyx_v_ifst2->_fst), __pyx_v_tfst.get(), (*__pyx_v_opts));
 
-  /* "pywrapfst.pyx":3624
+  /* "pywrapfst.pyx":3642
  *         _get_compose_filter(tostring(compose_filter))))
  *   fst.Intersect(deref(ifst1._fst), deref(ifst2._fst), tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -38727,13 +37784,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_intersect(str
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3624, __pyx_L1_error)
+  __pyx_t_3 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3642, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_3);
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3594
+  /* "pywrapfst.pyx":3612
  * 
  * 
  * cpdef _MutableFst intersect(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -38753,9 +37810,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_intersect(str
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_35intersect(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_34intersect[] = "\n  intersect(ifst1, ifst2, compose_filter=\"auto\", connect=True)\n\n  Constructively intersects two FSTs.\n\n  This operation computes the intersection (Hadamard product) of two FSTs.\n  Only strings that are in both automata are retained in the result. The two\n  arguments must be acceptors. One of the arguments must be label-sorted (or\n  otherwise support appropriate matchers).\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    compose_filter: A string matching a known composition filter; one of:\n        \"alt_sequence\", \"auto\", \"match\", \"null\", \"sequence\", \"trivial\".\n    connect: Should output be trimmed?\n\n  Returns:\n    An intersected FST.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_35intersect(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_37intersect(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_36intersect[] = "\n  intersect(ifst1, ifst2, compose_filter=\"auto\", connect=True)\n\n  Constructively intersects two FSTs.\n\n  This operation computes the intersection (Hadamard product) of two FSTs.\n  Only strings that are in both automata are retained in the result. The two\n  arguments must be acceptors. One of the arguments must be label-sorted (or\n  otherwise support appropriate matchers).\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    compose_filter: A string matching a known composition filter; one of:\n        \"alt_sequence\", \"auto\", \"match\", \"null\", \"sequence\", \"trivial\".\n    connect: Should output be trimmed?\n\n  Returns:\n    An intersected FST.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_37intersect(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1 = 0;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2 = 0;
   PyObject *__pyx_v_compose_filter = 0;
@@ -38791,7 +37848,7 @@ static PyObject *__pyx_pw_9pywrapfst_35intersect(PyObject *__pyx_self, PyObject
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ifst2)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("intersect", 0, 2, 4, 1); __PYX_ERR(0, 3594, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("intersect", 0, 2, 4, 1); __PYX_ERR(0, 3612, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
@@ -38807,7 +37864,7 @@ static PyObject *__pyx_pw_9pywrapfst_35intersect(PyObject *__pyx_self, PyObject
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "intersect") < 0)) __PYX_ERR(0, 3594, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "intersect") < 0)) __PYX_ERR(0, 3612, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -38825,10 +37882,10 @@ static PyObject *__pyx_pw_9pywrapfst_35intersect(PyObject *__pyx_self, PyObject
     __pyx_v_ifst2 = ((struct __pyx_obj_9pywrapfst__Fst *)values[1]);
     __pyx_v_compose_filter = values[2];
     if (values[3]) {
-      __pyx_v_connect = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_connect == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3597, __pyx_L3_error)
+      __pyx_v_connect = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_connect == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3615, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3597
+      /* "pywrapfst.pyx":3615
  *                             _Fst ifst2,
  *                             compose_filter=b"auto",
  *                             bool connect=True):             # <<<<<<<<<<<<<<
@@ -38840,17 +37897,17 @@ static PyObject *__pyx_pw_9pywrapfst_35intersect(PyObject *__pyx_self, PyObject
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("intersect", 0, 2, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3594, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("intersect", 0, 2, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3612, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.intersect", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3594, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3595, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_34intersect(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_compose_filter, __pyx_v_connect);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3612, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3613, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_36intersect(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_compose_filter, __pyx_v_connect);
 
-  /* "pywrapfst.pyx":3594
+  /* "pywrapfst.pyx":3612
  * 
  * 
  * cpdef _MutableFst intersect(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -38867,7 +37924,7 @@ static PyObject *__pyx_pw_9pywrapfst_35intersect(PyObject *__pyx_self, PyObject
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_34intersect(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect) {
+static PyObject *__pyx_pf_9pywrapfst_36intersect(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, PyObject *__pyx_v_compose_filter, bool __pyx_v_connect) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -38877,7 +37934,7 @@ static PyObject *__pyx_pf_9pywrapfst_34intersect(CYTHON_UNUSED PyObject *__pyx_s
   __pyx_t_2.__pyx_n = 2;
   __pyx_t_2.compose_filter = __pyx_v_compose_filter;
   __pyx_t_2.connect = __pyx_v_connect;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_intersect(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3594, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_intersect(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3612, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -38894,7 +37951,7 @@ static PyObject *__pyx_pf_9pywrapfst_34intersect(CYTHON_UNUSED PyObject *__pyx_s
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3627
+/* "pywrapfst.pyx":3645
  * 
  * 
  * cpdef bool isomorphic(_Fst ifst1, _Fst ifst2, float delta=fst.kDelta):             # <<<<<<<<<<<<<<
@@ -38902,9 +37959,9 @@ static PyObject *__pyx_pf_9pywrapfst_34intersect(CYTHON_UNUSED PyObject *__pyx_s
  *   isomorphic(ifst1, ifst2, delta=0.0009765625)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_37isomorphic(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_39isomorphic(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static bool __pyx_f_9pywrapfst_isomorphic(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_isomorphic *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__75;
+  float __pyx_v_delta = __pyx_k__39;
   bool __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("isomorphic", 0);
@@ -38914,7 +37971,7 @@ static bool __pyx_f_9pywrapfst_isomorphic(struct __pyx_obj_9pywrapfst__Fst *__py
     }
   }
 
-  /* "pywrapfst.pyx":3650
+  /* "pywrapfst.pyx":3668
  *   See also: `equal`, `equivalent`, `randequivalent`.
  *   """
  *   return fst.Isomorphic(deref(ifst1._fst), deref(ifst2._fst), delta)             # <<<<<<<<<<<<<<
@@ -38923,16 +37980,16 @@ static bool __pyx_f_9pywrapfst_isomorphic(struct __pyx_obj_9pywrapfst__Fst *__py
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3650, __pyx_L1_error)
+    __PYX_ERR(0, 3668, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst2) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3650, __pyx_L1_error)
+    __PYX_ERR(0, 3668, __pyx_L1_error)
   }
   __pyx_r = fst::script::Isomorphic((*__pyx_v_ifst1->_fst), (*__pyx_v_ifst2->_fst), __pyx_v_delta);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3627
+  /* "pywrapfst.pyx":3645
  * 
  * 
  * cpdef bool isomorphic(_Fst ifst1, _Fst ifst2, float delta=fst.kDelta):             # <<<<<<<<<<<<<<
@@ -38950,9 +38007,9 @@ static bool __pyx_f_9pywrapfst_isomorphic(struct __pyx_obj_9pywrapfst__Fst *__py
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_37isomorphic(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_36isomorphic[] = "\n  isomorphic(ifst1, ifst2, delta=0.0009765625)\n\n  Are the two acceptors isomorphic?\n\n  This operation determines if two transducers with a certain required\n  determinism have the same states, irrespective of numbering, and the same\n  transitions with the same labels and weights, irrespective of ordering. In\n  other words, FSTs A, B are isomorphic if and only if the states of A can be\n  renumbered and the transitions leaving each state reordered so the two are\n  equal (according to the definition given in `equal`).\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    delta: Comparison/quantization delta.\n\n  Returns:\n    True if the two transducers satisfy the above condition, else False.\n\n  See also: `equal`, `equivalent`, `randequivalent`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_37isomorphic(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_39isomorphic(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_38isomorphic[] = "\n  isomorphic(ifst1, ifst2, delta=0.0009765625)\n\n  Are the two acceptors isomorphic?\n\n  This operation determines if two transducers with a certain required\n  determinism have the same states, irrespective of numbering, and the same\n  transitions with the same labels and weights, irrespective of ordering. In\n  other words, FSTs A, B are isomorphic if and only if the states of A can be\n  renumbered and the transitions leaving each state reordered so the two are\n  equal (according to the definition given in `equal`).\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    delta: Comparison/quantization delta.\n\n  Returns:\n    True if the two transducers satisfy the above condition, else False.\n\n  See also: `equal`, `equivalent`, `randequivalent`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_39isomorphic(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1 = 0;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2 = 0;
   float __pyx_v_delta;
@@ -38984,7 +38041,7 @@ static PyObject *__pyx_pw_9pywrapfst_37isomorphic(PyObject *__pyx_self, PyObject
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ifst2)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("isomorphic", 0, 2, 3, 1); __PYX_ERR(0, 3627, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("isomorphic", 0, 2, 3, 1); __PYX_ERR(0, 3645, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
@@ -38994,7 +38051,7 @@ static PyObject *__pyx_pw_9pywrapfst_37isomorphic(PyObject *__pyx_self, PyObject
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "isomorphic") < 0)) __PYX_ERR(0, 3627, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "isomorphic") < 0)) __PYX_ERR(0, 3645, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -39009,22 +38066,22 @@ static PyObject *__pyx_pw_9pywrapfst_37isomorphic(PyObject *__pyx_self, PyObject
     __pyx_v_ifst1 = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     __pyx_v_ifst2 = ((struct __pyx_obj_9pywrapfst__Fst *)values[1]);
     if (values[2]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3627, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3645, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__75;
+      __pyx_v_delta = __pyx_k__39;
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("isomorphic", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3627, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("isomorphic", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3645, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.isomorphic", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3627, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3627, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_36isomorphic(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_delta);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3645, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3645, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_38isomorphic(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_delta);
 
   /* function exit code */
   goto __pyx_L0;
@@ -39035,7 +38092,7 @@ static PyObject *__pyx_pw_9pywrapfst_37isomorphic(PyObject *__pyx_self, PyObject
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_36isomorphic(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta) {
+static PyObject *__pyx_pf_9pywrapfst_38isomorphic(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, float __pyx_v_delta) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   bool __pyx_t_1;
@@ -39046,7 +38103,7 @@ static PyObject *__pyx_pf_9pywrapfst_36isomorphic(CYTHON_UNUSED PyObject *__pyx_
   __pyx_t_2.__pyx_n = 1;
   __pyx_t_2.delta = __pyx_v_delta;
   __pyx_t_1 = __pyx_f_9pywrapfst_isomorphic(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2); 
-  __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3627, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3645, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
@@ -39063,7 +38120,7 @@ static PyObject *__pyx_pf_9pywrapfst_36isomorphic(CYTHON_UNUSED PyObject *__pyx_
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3653
+/* "pywrapfst.pyx":3671
  * 
  * 
  * cpdef _MutableFst prune(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -39071,12 +38128,12 @@ static PyObject *__pyx_pf_9pywrapfst_36isomorphic(CYTHON_UNUSED PyObject *__pyx_
  *                         int64 nstate=fst.kNoStateId,
  */
 
-static PyObject *__pyx_pw_9pywrapfst_39prune(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_41prune(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_prune(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_prune *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__76;
-  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__77;
+  float __pyx_v_delta = __pyx_k__40;
+  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__41;
 
-  /* "pywrapfst.pyx":3656
+  /* "pywrapfst.pyx":3674
  *                         float delta=fst.kDelta,
  *                         int64 nstate=fst.kNoStateId,
  *                         weight=None):             # <<<<<<<<<<<<<<
@@ -39103,7 +38160,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_prune(struct
     }
   }
 
-  /* "pywrapfst.pyx":3680
+  /* "pywrapfst.pyx":3698
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -39112,11 +38169,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_prune(struct
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3680, __pyx_L1_error)
+    __PYX_ERR(0, 3698, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":3681
+  /* "pywrapfst.pyx":3699
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   cdef fst.WeightClass wc = _get_WeightClass_or_Zero(ifst.weight_type(), weight)             # <<<<<<<<<<<<<<
@@ -39125,12 +38182,12 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_prune(struct
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-    __PYX_ERR(0, 3681, __pyx_L1_error)
+    __PYX_ERR(0, 3699, __pyx_L1_error)
   }
-  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3681, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3699, __pyx_L1_error)
   __pyx_v_wc = __pyx_t_1;
 
-  /* "pywrapfst.pyx":3682
+  /* "pywrapfst.pyx":3700
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   cdef fst.WeightClass wc = _get_WeightClass_or_Zero(ifst.weight_type(), weight)
  *   fst.Prune(deref(ifst._fst), tfst.get(), wc, nstate, delta)             # <<<<<<<<<<<<<<
@@ -39139,11 +38196,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_prune(struct
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3682, __pyx_L1_error)
+    __PYX_ERR(0, 3700, __pyx_L1_error)
   }
   fst::script::Prune((*__pyx_v_ifst->_fst), __pyx_v_tfst.get(), __pyx_v_wc, __pyx_v_nstate, __pyx_v_delta);
 
-  /* "pywrapfst.pyx":3683
+  /* "pywrapfst.pyx":3701
  *   cdef fst.WeightClass wc = _get_WeightClass_or_Zero(ifst.weight_type(), weight)
  *   fst.Prune(deref(ifst._fst), tfst.get(), wc, nstate, delta)
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -39151,13 +38208,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_prune(struct
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3683, __pyx_L1_error)
+  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3701, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_2);
   __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3653
+  /* "pywrapfst.pyx":3671
  * 
  * 
  * cpdef _MutableFst prune(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -39177,9 +38234,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_prune(struct
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_39prune(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_38prune[] = "\n  prune(ifst, delta=0.0009765625, nstate=NO_STATE_ID, weight=None)\n\n  Constructively removes paths with weights below a certain threshold.\n\n  This operation deletes states and arcs in the input FST that do not belong\n  to a successful path whose weight is no more (w.r.t the natural semiring\n  order) than the threshold t \\otimes-times the weight of the shortest path in\n  the input FST. Weights must be commutative and have the path property.\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    nstate: State number threshold.\n    weight: A Weight or weight string indicating the desired weight threshold\n        below which paths are pruned; if omitted, no paths are pruned.\n\n  Returns:\n    A pruned FST.\n\n  See also: The destructive variant.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_39prune(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_41prune(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_40prune[] = "\n  prune(ifst, delta=0.0009765625, nstate=NO_STATE_ID, weight=None)\n\n  Constructively removes paths with weights below a certain threshold.\n\n  This operation deletes states and arcs in the input FST that do not belong\n  to a successful path whose weight is no more (w.r.t the natural semiring\n  order) than the threshold t \\otimes-times the weight of the shortest path in\n  the input FST. Weights must be commutative and have the path property.\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    nstate: State number threshold.\n    weight: A Weight or weight string indicating the desired weight threshold\n        below which paths are pruned; if omitted, no paths are pruned.\n\n  Returns:\n    A pruned FST.\n\n  See also: The destructive variant.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_41prune(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   float __pyx_v_delta;
   __pyx_t_10basictypes_int64 __pyx_v_nstate;
@@ -39191,7 +38248,7 @@ static PyObject *__pyx_pw_9pywrapfst_39prune(PyObject *__pyx_self, PyObject *__p
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_ifst,&__pyx_n_s_delta,&__pyx_n_s_nstate,&__pyx_n_s_weight,0};
     PyObject* values[4] = {0,0,0,0};
 
-    /* "pywrapfst.pyx":3656
+    /* "pywrapfst.pyx":3674
  *                         float delta=fst.kDelta,
  *                         int64 nstate=fst.kNoStateId,
  *                         weight=None):             # <<<<<<<<<<<<<<
@@ -39239,7 +38296,7 @@ static PyObject *__pyx_pw_9pywrapfst_39prune(PyObject *__pyx_self, PyObject *__p
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "prune") < 0)) __PYX_ERR(0, 3653, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "prune") < 0)) __PYX_ERR(0, 3671, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -39256,29 +38313,29 @@ static PyObject *__pyx_pw_9pywrapfst_39prune(PyObject *__pyx_self, PyObject *__p
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3654, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3672, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__76;
+      __pyx_v_delta = __pyx_k__40;
     }
     if (values[2]) {
-      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[2]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3655, __pyx_L3_error)
+      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[2]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3673, __pyx_L3_error)
     } else {
-      __pyx_v_nstate = __pyx_k__77;
+      __pyx_v_nstate = __pyx_k__41;
     }
     __pyx_v_weight = values[3];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("prune", 0, 1, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3653, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("prune", 0, 1, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3671, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.prune", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3653, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_38prune(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_nstate, __pyx_v_weight);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3671, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_40prune(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_nstate, __pyx_v_weight);
 
-  /* "pywrapfst.pyx":3653
+  /* "pywrapfst.pyx":3671
  * 
  * 
  * cpdef _MutableFst prune(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -39295,7 +38352,7 @@ static PyObject *__pyx_pw_9pywrapfst_39prune(PyObject *__pyx_self, PyObject *__p
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_38prune(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_weight) {
+static PyObject *__pyx_pf_9pywrapfst_40prune(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_weight) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -39306,7 +38363,7 @@ static PyObject *__pyx_pf_9pywrapfst_38prune(CYTHON_UNUSED PyObject *__pyx_self,
   __pyx_t_2.delta = __pyx_v_delta;
   __pyx_t_2.nstate = __pyx_v_nstate;
   __pyx_t_2.weight = __pyx_v_weight;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_prune(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3653, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_prune(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3671, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -39323,7 +38380,7 @@ static PyObject *__pyx_pf_9pywrapfst_38prune(CYTHON_UNUSED PyObject *__pyx_self,
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3686
+/* "pywrapfst.pyx":3704
  * 
  * 
  * cpdef _MutableFst push(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -39331,11 +38388,11 @@ static PyObject *__pyx_pf_9pywrapfst_38prune(CYTHON_UNUSED PyObject *__pyx_self,
  *                        bool push_weights=False,
  */
 
-static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_43push(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_push *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__78;
+  float __pyx_v_delta = __pyx_k__42;
 
-  /* "pywrapfst.pyx":3688
+  /* "pywrapfst.pyx":3706
  * cpdef _MutableFst push(_Fst ifst,
  *                        float delta=fst.kDelta,
  *                        bool push_weights=False,             # <<<<<<<<<<<<<<
@@ -39344,7 +38401,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
  */
   bool __pyx_v_push_weights = ((bool)0);
 
-  /* "pywrapfst.pyx":3689
+  /* "pywrapfst.pyx":3707
  *                        float delta=fst.kDelta,
  *                        bool push_weights=False,
  *                        bool push_labels=False,             # <<<<<<<<<<<<<<
@@ -39353,7 +38410,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
  */
   bool __pyx_v_push_labels = ((bool)0);
 
-  /* "pywrapfst.pyx":3690
+  /* "pywrapfst.pyx":3708
  *                        bool push_weights=False,
  *                        bool push_labels=False,
  *                        bool remove_common_affix=False,             # <<<<<<<<<<<<<<
@@ -39362,7 +38419,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
  */
   bool __pyx_v_remove_common_affix = ((bool)0);
 
-  /* "pywrapfst.pyx":3691
+  /* "pywrapfst.pyx":3709
  *                        bool push_labels=False,
  *                        bool remove_common_affix=False,
  *                        bool remove_total_weight=False,             # <<<<<<<<<<<<<<
@@ -39371,7 +38428,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
  */
   bool __pyx_v_remove_total_weight = ((bool)0);
 
-  /* "pywrapfst.pyx":3692
+  /* "pywrapfst.pyx":3710
  *                        bool remove_common_affix=False,
  *                        bool remove_total_weight=False,
  *                        bool to_final=False):             # <<<<<<<<<<<<<<
@@ -39406,7 +38463,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
     }
   }
 
-  /* "pywrapfst.pyx":3732
+  /* "pywrapfst.pyx":3750
  *   # This is copied, almost verbatim, from nlp/fst/bin/fstpush.cc.
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -39415,11 +38472,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3732, __pyx_L1_error)
+    __PYX_ERR(0, 3750, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":3733
+  /* "pywrapfst.pyx":3751
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   cdef uint32 flags = fst.GetPushFlags(push_weights, push_labels,             # <<<<<<<<<<<<<<
@@ -39428,7 +38485,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
  */
   __pyx_v_flags = fst::script::GetPushFlags(__pyx_v_push_weights, __pyx_v_push_labels, __pyx_v_remove_common_affix, __pyx_v_remove_total_weight);
 
-  /* "pywrapfst.pyx":3735
+  /* "pywrapfst.pyx":3753
  *   cdef uint32 flags = fst.GetPushFlags(push_weights, push_labels,
  *                                        remove_common_affix, remove_total_weight)
  *   fst.Push(deref(ifst._fst), tfst.get(), flags, fst.GetReweightType(to_final),             # <<<<<<<<<<<<<<
@@ -39437,10 +38494,10 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3735, __pyx_L1_error)
+    __PYX_ERR(0, 3753, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":3736
+  /* "pywrapfst.pyx":3754
  *                                        remove_common_affix, remove_total_weight)
  *   fst.Push(deref(ifst._fst), tfst.get(), flags, fst.GetReweightType(to_final),
  *            delta)             # <<<<<<<<<<<<<<
@@ -39449,7 +38506,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
  */
   fst::script::Push((*__pyx_v_ifst->_fst), __pyx_v_tfst.get(), __pyx_v_flags, fst::script::GetReweightType(__pyx_v_to_final), __pyx_v_delta);
 
-  /* "pywrapfst.pyx":3737
+  /* "pywrapfst.pyx":3755
  *   fst.Push(deref(ifst._fst), tfst.get(), flags, fst.GetReweightType(to_final),
  *            delta)
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -39457,13 +38514,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3737, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3755, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3686
+  /* "pywrapfst.pyx":3704
  * 
  * 
  * cpdef _MutableFst push(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -39483,9 +38540,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_push(struct _
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_40push[] = "\n  push(ifst, delta=0.0009765625, push_weights=False, push_labels=False,\n       remove_common_affix=False, remove_total_weight=False, to_final=False)\n\n  Constructively pushes weights/labels towards initial or final states.\n\n  This operation produces an equivalent transducer by pushing the weights\n  and/or the labels towards the initial state or toward the final states.\n\n  When pushing weights towards the initial state, the sum of the weight of the\n  outgoing transitions and final weight at any non-initial state is equal to 1\n  in the resulting machine. When pushing weights towards the final states, the\n  sum of the weight of the incoming transitions at any state is equal to 1.\n  Weights need to be left distributive when pushing towards the initial state\n  and right distributive when pushing towards the final states.\n\n  Pushing labels towards the initial state consists in minimizing at every\n  state the length of the longest common prefix of the output labels of the\n  outgoing paths. Pushing labels towards the final states consists in\n  minimizing at every state the length of the longest common suffix of the\n  output labels of the incoming paths.\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    push_weights: Should weights be pushed?\n    push_labels: Should labels be pushed?\n    remove_common_affix: If pushing labels, should common prefix/suffix be\n        removed?\n    remove_total_weight: If pushing weights, should total weight be removed?\n    to_final: Push towards final states?\n\n  Returns:\n    An equivalent pushed FST.\n\n  See also: The destructive variant.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_43push(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_42push[] = "\n  push(ifst, delta=0.0009765625, push_weights=False, push_labels=False,\n       remove_common_affix=False, remove_total_weight=False, to_final=False)\n\n  Constructively pushes weights/labels towards initial or final states.\n\n  This operation produces an equivalent transducer by pushing the weights\n  and/or the labels towards the initial state or toward the final states.\n\n  When pushing weights towards the initial state, the sum of the weight of the\n  outgoing transitions and final weight at any non-initial state is equal to 1\n  in the resulting machine. When pushing weights towards the final states, the\n  sum of the weight of the incoming transitions at any state is equal to 1.\n  Weights need to be left distributive when pushing towards the initial state\n  and right distributive when pushing towards the final states.\n\n  Pushing labels towards the initial state consists in minimizing at every\n  state the length of the longest common prefix of the output labels of the\n  outgoing paths. Pushing labels towards the final states consists in\n  minimizing at every state the length of the longest common suffix of the\n  output labels of the incoming paths.\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    push_weights: Should weights be pushed?\n    push_labels: Should labels be pushed?\n    remove_common_affix: If pushing labels, should common prefix/suffix be\n        removed?\n    remove_total_weight: If pushing weights, should total weight be removed?\n    to_final: Push towards final states?\n\n  Returns:\n    An equivalent pushed FST.\n\n  See also: The destructive variant.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_43push(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   float __pyx_v_delta;
   bool __pyx_v_push_weights;
@@ -39563,7 +38620,7 @@ static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__py
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "push") < 0)) __PYX_ERR(0, 3686, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "push") < 0)) __PYX_ERR(0, 3704, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -39586,15 +38643,15 @@ static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__py
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3687, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3705, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__78;
+      __pyx_v_delta = __pyx_k__42;
     }
     if (values[2]) {
-      __pyx_v_push_weights = __Pyx_PyObject_IsTrue(values[2]); if (unlikely((__pyx_v_push_weights == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3688, __pyx_L3_error)
+      __pyx_v_push_weights = __Pyx_PyObject_IsTrue(values[2]); if (unlikely((__pyx_v_push_weights == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3706, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3688
+      /* "pywrapfst.pyx":3706
  * cpdef _MutableFst push(_Fst ifst,
  *                        float delta=fst.kDelta,
  *                        bool push_weights=False,             # <<<<<<<<<<<<<<
@@ -39604,10 +38661,10 @@ static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__py
       __pyx_v_push_weights = ((bool)0);
     }
     if (values[3]) {
-      __pyx_v_push_labels = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_push_labels == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3689, __pyx_L3_error)
+      __pyx_v_push_labels = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_push_labels == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3707, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3689
+      /* "pywrapfst.pyx":3707
  *                        float delta=fst.kDelta,
  *                        bool push_weights=False,
  *                        bool push_labels=False,             # <<<<<<<<<<<<<<
@@ -39617,10 +38674,10 @@ static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__py
       __pyx_v_push_labels = ((bool)0);
     }
     if (values[4]) {
-      __pyx_v_remove_common_affix = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_remove_common_affix == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3690, __pyx_L3_error)
+      __pyx_v_remove_common_affix = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_remove_common_affix == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3708, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3690
+      /* "pywrapfst.pyx":3708
  *                        bool push_weights=False,
  *                        bool push_labels=False,
  *                        bool remove_common_affix=False,             # <<<<<<<<<<<<<<
@@ -39630,10 +38687,10 @@ static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__py
       __pyx_v_remove_common_affix = ((bool)0);
     }
     if (values[5]) {
-      __pyx_v_remove_total_weight = __Pyx_PyObject_IsTrue(values[5]); if (unlikely((__pyx_v_remove_total_weight == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3691, __pyx_L3_error)
+      __pyx_v_remove_total_weight = __Pyx_PyObject_IsTrue(values[5]); if (unlikely((__pyx_v_remove_total_weight == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3709, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3691
+      /* "pywrapfst.pyx":3709
  *                        bool push_labels=False,
  *                        bool remove_common_affix=False,
  *                        bool remove_total_weight=False,             # <<<<<<<<<<<<<<
@@ -39643,10 +38700,10 @@ static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__py
       __pyx_v_remove_total_weight = ((bool)0);
     }
     if (values[6]) {
-      __pyx_v_to_final = __Pyx_PyObject_IsTrue(values[6]); if (unlikely((__pyx_v_to_final == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3692, __pyx_L3_error)
+      __pyx_v_to_final = __Pyx_PyObject_IsTrue(values[6]); if (unlikely((__pyx_v_to_final == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3710, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3692
+      /* "pywrapfst.pyx":3710
  *                        bool remove_common_affix=False,
  *                        bool remove_total_weight=False,
  *                        bool to_final=False):             # <<<<<<<<<<<<<<
@@ -39658,16 +38715,16 @@ static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__py
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("push", 0, 1, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3686, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("push", 0, 1, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3704, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.push", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3686, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_40push(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_push_weights, __pyx_v_push_labels, __pyx_v_remove_common_affix, __pyx_v_remove_total_weight, __pyx_v_to_final);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3704, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_42push(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_push_weights, __pyx_v_push_labels, __pyx_v_remove_common_affix, __pyx_v_remove_total_weight, __pyx_v_to_final);
 
-  /* "pywrapfst.pyx":3686
+  /* "pywrapfst.pyx":3704
  * 
  * 
  * cpdef _MutableFst push(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -39684,7 +38741,7 @@ static PyObject *__pyx_pw_9pywrapfst_41push(PyObject *__pyx_self, PyObject *__py
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_40push(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, bool __pyx_v_push_weights, bool __pyx_v_push_labels, bool __pyx_v_remove_common_affix, bool __pyx_v_remove_total_weight, bool __pyx_v_to_final) {
+static PyObject *__pyx_pf_9pywrapfst_42push(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, bool __pyx_v_push_weights, bool __pyx_v_push_labels, bool __pyx_v_remove_common_affix, bool __pyx_v_remove_total_weight, bool __pyx_v_to_final) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -39698,7 +38755,7 @@ static PyObject *__pyx_pf_9pywrapfst_40push(CYTHON_UNUSED PyObject *__pyx_self,
   __pyx_t_2.remove_common_affix = __pyx_v_remove_common_affix;
   __pyx_t_2.remove_total_weight = __pyx_v_remove_total_weight;
   __pyx_t_2.to_final = __pyx_v_to_final;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_push(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3686, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_push(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3704, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -39715,7 +38772,7 @@ static PyObject *__pyx_pf_9pywrapfst_40push(CYTHON_UNUSED PyObject *__pyx_self,
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3740
+/* "pywrapfst.pyx":3758
  * 
  * 
  * cpdef bool randequivalent(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -39723,13 +38780,13 @@ static PyObject *__pyx_pf_9pywrapfst_40push(CYTHON_UNUSED PyObject *__pyx_self,
  *                           int32 npath=1,
  */
 
-static PyObject *__pyx_pw_9pywrapfst_43randequivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_45randequivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static bool __pyx_f_9pywrapfst_randequivalent(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_randequivalent *__pyx_optional_args) {
   __pyx_t_10basictypes_int32 __pyx_v_npath = ((__pyx_t_10basictypes_int32)1);
-  float __pyx_v_delta = __pyx_k__79;
+  float __pyx_v_delta = __pyx_k__43;
   time_t __pyx_v_seed = ((time_t)0);
   PyObject *__pyx_v_select = ((PyObject *)__pyx_n_b_uniform);
-  __pyx_t_10basictypes_int32 __pyx_v_max_length = __pyx_k__80;
+  __pyx_t_10basictypes_int32 __pyx_v_max_length = __pyx_k__44;
   enum fst::script::RandArcSelection __pyx_v_ras;
   std::unique_ptr<fst::RandGenOptions<enum fst::script::RandArcSelection> >  __pyx_v_opts;
   bool __pyx_r;
@@ -39756,18 +38813,18 @@ static bool __pyx_f_9pywrapfst_randequivalent(struct __pyx_obj_9pywrapfst__Fst *
     }
   }
 
-  /* "pywrapfst.pyx":3775
+  /* "pywrapfst.pyx":3793
  *   See also: `equal`, `equivalent`, `isomorphic`, `randgen`.
  *   """
  *   cdef fst.RandArcSelection ras = _get_rand_arc_selection(tostring(select))             # <<<<<<<<<<<<<<
  *   cdef unique_ptr[fst.RandGenOptions[fst.RandArcSelection]] opts
  *   # The three trailing options will be ignored by RandEquivalent.
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_select, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3775, __pyx_L1_error)
-  __pyx_t_2 = __pyx_f_9pywrapfst__get_rand_arc_selection(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3775, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_select, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3793, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst__get_rand_arc_selection(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3793, __pyx_L1_error)
   __pyx_v_ras = __pyx_t_2;
 
-  /* "pywrapfst.pyx":3778
+  /* "pywrapfst.pyx":3796
  *   cdef unique_ptr[fst.RandGenOptions[fst.RandArcSelection]] opts
  *   # The three trailing options will be ignored by RandEquivalent.
  *   opts.reset(new fst.RandGenOptions[fst.RandArcSelection](ras, max_length,             # <<<<<<<<<<<<<<
@@ -39776,7 +38833,7 @@ static bool __pyx_f_9pywrapfst_randequivalent(struct __pyx_obj_9pywrapfst__Fst *
  */
   __pyx_v_opts.reset(new fst::RandGenOptions<enum fst::script::RandArcSelection> (__pyx_v_ras, __pyx_v_max_length, 1, 0, 0));
 
-  /* "pywrapfst.pyx":3780
+  /* "pywrapfst.pyx":3798
  *   opts.reset(new fst.RandGenOptions[fst.RandArcSelection](ras, max_length,
  *                                                           1, False, False))
  *   if seed == 0:             # <<<<<<<<<<<<<<
@@ -39786,7 +38843,7 @@ static bool __pyx_f_9pywrapfst_randequivalent(struct __pyx_obj_9pywrapfst__Fst *
   __pyx_t_3 = ((__pyx_v_seed == 0) != 0);
   if (__pyx_t_3) {
 
-    /* "pywrapfst.pyx":3781
+    /* "pywrapfst.pyx":3799
  *                                                           1, False, False))
  *   if seed == 0:
  *     seed = time(NULL) + getpid()             # <<<<<<<<<<<<<<
@@ -39795,7 +38852,7 @@ static bool __pyx_f_9pywrapfst_randequivalent(struct __pyx_obj_9pywrapfst__Fst *
  */
     __pyx_v_seed = (time(NULL) + getpid());
 
-    /* "pywrapfst.pyx":3780
+    /* "pywrapfst.pyx":3798
  *   opts.reset(new fst.RandGenOptions[fst.RandArcSelection](ras, max_length,
  *                                                           1, False, False))
  *   if seed == 0:             # <<<<<<<<<<<<<<
@@ -39804,7 +38861,7 @@ static bool __pyx_f_9pywrapfst_randequivalent(struct __pyx_obj_9pywrapfst__Fst *
  */
   }
 
-  /* "pywrapfst.pyx":3782
+  /* "pywrapfst.pyx":3800
  *   if seed == 0:
  *     seed = time(NULL) + getpid()
  *   return fst.RandEquivalent(deref(ifst1._fst), deref(ifst2._fst), npath, delta,             # <<<<<<<<<<<<<<
@@ -39813,14 +38870,14 @@ static bool __pyx_f_9pywrapfst_randequivalent(struct __pyx_obj_9pywrapfst__Fst *
  */
   if (unlikely(((PyObject *)__pyx_v_ifst1) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3782, __pyx_L1_error)
+    __PYX_ERR(0, 3800, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_ifst2) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3782, __pyx_L1_error)
+    __PYX_ERR(0, 3800, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":3783
+  /* "pywrapfst.pyx":3801
  *     seed = time(NULL) + getpid()
  *   return fst.RandEquivalent(deref(ifst1._fst), deref(ifst2._fst), npath, delta,
  *                            seed, deref(opts))             # <<<<<<<<<<<<<<
@@ -39830,7 +38887,7 @@ static bool __pyx_f_9pywrapfst_randequivalent(struct __pyx_obj_9pywrapfst__Fst *
   __pyx_r = fst::script::RandEquivalent((*__pyx_v_ifst1->_fst), (*__pyx_v_ifst2->_fst), __pyx_v_npath, __pyx_v_delta, __pyx_v_seed, (*__pyx_v_opts));
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3740
+  /* "pywrapfst.pyx":3758
  * 
  * 
  * cpdef bool randequivalent(_Fst ifst1,             # <<<<<<<<<<<<<<
@@ -39848,9 +38905,9 @@ static bool __pyx_f_9pywrapfst_randequivalent(struct __pyx_obj_9pywrapfst__Fst *
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_43randequivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_42randequivalent[] = "\n  randequivalent(ifst1, ifst2, npath=1, delta=0.0009765625, seed=0,\n                 select=\"uniform\", max_length=2147483647)\n\n  Are two acceptors stochastically equivalent?\n\n  This operation tests whether two FSTs are equivalent by randomly generating\n  paths alternatively in each of the two FSTs. For each randomly generated path,\n  the algorithm computes for each of the two FSTs the sum of the weights of all\n  the successful paths sharing the same input and output labels as the randomly\n  generated path and checks that these two values are within `delta`.\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    npath: The number of random paths to generate.\n    delta: Comparison/quantization delta.\n    seed: An optional seed value for random path generation; if zero, the\n        current time and process ID is used.\n    select: A string matching a known random arc selection type; one of:\n        \"uniform\", \"log_prob\", \"fast_log_prob\".\n    max_length: The maximum length of each random path.\n\n  Returns:\n    True if the two transducers satisfy the above condition, else False.\n\n  See also: `equal`, `equivalent`, `isomorphic`, `randgen`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_43randequivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_45randequivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_44randequivalent[] = "\n  randequivalent(ifst1, ifst2, npath=1, delta=0.0009765625, seed=0,\n                 select=\"uniform\", max_length=2147483647)\n\n  Are two acceptors stochastically equivalent?\n\n  This operation tests whether two FSTs are equivalent by randomly generating\n  paths alternatively in each of the two FSTs. For each randomly generated path,\n  the algorithm computes for each of the two FSTs the sum of the weights of all\n  the successful paths sharing the same input and output labels as the randomly\n  generated path and checks that these two values are within `delta`.\n\n  Args:\n    ifst1: The first input FST.\n    ifst2: The second input FST.\n    npath: The number of random paths to generate.\n    delta: Comparison/quantization delta.\n    seed: An optional seed value for random path generation; if zero, the\n        current time and process ID is used.\n    select: A string matching a known random arc selection type; one of:\n        \"uniform\", \"log_prob\", \"fast_log_prob\".\n    max_length: The maximum length of each random path.\n\n  Returns:\n    True if the two transducers satisfy the above condition, else False.\n\n  See also: `equal`, `equivalent`, `isomorphic`, `randgen`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_45randequivalent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1 = 0;
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2 = 0;
   __pyx_t_10basictypes_int32 __pyx_v_npath;
@@ -39895,7 +38952,7 @@ static PyObject *__pyx_pw_9pywrapfst_43randequivalent(PyObject *__pyx_self, PyOb
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ifst2)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("randequivalent", 0, 2, 7, 1); __PYX_ERR(0, 3740, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("randequivalent", 0, 2, 7, 1); __PYX_ERR(0, 3758, __pyx_L3_error)
         }
         CYTHON_FALLTHROUGH;
         case  2:
@@ -39929,7 +38986,7 @@ static PyObject *__pyx_pw_9pywrapfst_43randequivalent(PyObject *__pyx_self, PyOb
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "randequivalent") < 0)) __PYX_ERR(0, 3740, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "randequivalent") < 0)) __PYX_ERR(0, 3758, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -39952,38 +39009,38 @@ static PyObject *__pyx_pw_9pywrapfst_43randequivalent(PyObject *__pyx_self, PyOb
     __pyx_v_ifst1 = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     __pyx_v_ifst2 = ((struct __pyx_obj_9pywrapfst__Fst *)values[1]);
     if (values[2]) {
-      __pyx_v_npath = __Pyx_PyInt_As_int32_t(values[2]); if (unlikely((__pyx_v_npath == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3742, __pyx_L3_error)
+      __pyx_v_npath = __Pyx_PyInt_As_int32_t(values[2]); if (unlikely((__pyx_v_npath == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3760, __pyx_L3_error)
     } else {
       __pyx_v_npath = ((__pyx_t_10basictypes_int32)1);
     }
     if (values[3]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[3]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3743, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[3]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3761, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__79;
+      __pyx_v_delta = __pyx_k__43;
     }
     if (values[4]) {
-      __pyx_v_seed = __Pyx_PyInt_As_time_t(values[4]); if (unlikely((__pyx_v_seed == ((time_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3744, __pyx_L3_error)
+      __pyx_v_seed = __Pyx_PyInt_As_time_t(values[4]); if (unlikely((__pyx_v_seed == ((time_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3762, __pyx_L3_error)
     } else {
       __pyx_v_seed = ((time_t)0);
     }
     __pyx_v_select = values[5];
     if (values[6]) {
-      __pyx_v_max_length = __Pyx_PyInt_As_int32_t(values[6]); if (unlikely((__pyx_v_max_length == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3746, __pyx_L3_error)
+      __pyx_v_max_length = __Pyx_PyInt_As_int32_t(values[6]); if (unlikely((__pyx_v_max_length == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3764, __pyx_L3_error)
     } else {
-      __pyx_v_max_length = __pyx_k__80;
+      __pyx_v_max_length = __pyx_k__44;
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("randequivalent", 0, 2, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3740, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("randequivalent", 0, 2, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3758, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.randequivalent", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3740, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3741, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_42randequivalent(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_npath, __pyx_v_delta, __pyx_v_seed, __pyx_v_select, __pyx_v_max_length);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst1), __pyx_ptype_9pywrapfst__Fst, 1, "ifst1", 0))) __PYX_ERR(0, 3758, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst2), __pyx_ptype_9pywrapfst__Fst, 1, "ifst2", 0))) __PYX_ERR(0, 3759, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_44randequivalent(__pyx_self, __pyx_v_ifst1, __pyx_v_ifst2, __pyx_v_npath, __pyx_v_delta, __pyx_v_seed, __pyx_v_select, __pyx_v_max_length);
 
   /* function exit code */
   goto __pyx_L0;
@@ -39994,7 +39051,7 @@ static PyObject *__pyx_pw_9pywrapfst_43randequivalent(PyObject *__pyx_self, PyOb
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_42randequivalent(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, __pyx_t_10basictypes_int32 __pyx_v_npath, float __pyx_v_delta, time_t __pyx_v_seed, PyObject *__pyx_v_select, __pyx_t_10basictypes_int32 __pyx_v_max_length) {
+static PyObject *__pyx_pf_9pywrapfst_44randequivalent(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst1, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst2, __pyx_t_10basictypes_int32 __pyx_v_npath, float __pyx_v_delta, time_t __pyx_v_seed, PyObject *__pyx_v_select, __pyx_t_10basictypes_int32 __pyx_v_max_length) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   bool __pyx_t_1;
@@ -40008,8 +39065,8 @@ static PyObject *__pyx_pf_9pywrapfst_42randequivalent(CYTHON_UNUSED PyObject *__
   __pyx_t_2.seed = __pyx_v_seed;
   __pyx_t_2.select = __pyx_v_select;
   __pyx_t_2.max_length = __pyx_v_max_length;
-  __pyx_t_1 = __pyx_f_9pywrapfst_randequivalent(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2); if (unlikely(__pyx_t_1 == ((bool)-1) && PyErr_Occurred())) __PYX_ERR(0, 3740, __pyx_L1_error)
-  __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3740, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_randequivalent(__pyx_v_ifst1, __pyx_v_ifst2, 0, &__pyx_t_2); if (unlikely(__pyx_t_1 == ((bool)-1) && PyErr_Occurred())) __PYX_ERR(0, 3758, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3758, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
@@ -40026,7 +39083,7 @@ static PyObject *__pyx_pf_9pywrapfst_42randequivalent(CYTHON_UNUSED PyObject *__
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3786
+/* "pywrapfst.pyx":3804
  * 
  * 
  * cpdef _MutableFst randgen(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -40034,14 +39091,14 @@ static PyObject *__pyx_pf_9pywrapfst_42randequivalent(CYTHON_UNUSED PyObject *__
  *                           time_t seed=0,
  */
 
-static PyObject *__pyx_pw_9pywrapfst_45randgen(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_47randgen(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_randgen *__pyx_optional_args) {
   __pyx_t_10basictypes_int32 __pyx_v_npath = ((__pyx_t_10basictypes_int32)1);
   time_t __pyx_v_seed = ((time_t)0);
   PyObject *__pyx_v_select = ((PyObject *)__pyx_n_b_uniform);
-  __pyx_t_10basictypes_int32 __pyx_v_max_length = __pyx_k__81;
+  __pyx_t_10basictypes_int32 __pyx_v_max_length = __pyx_k__45;
 
-  /* "pywrapfst.pyx":3791
+  /* "pywrapfst.pyx":3809
  *                           select=b"uniform",
  *                           int32 max_length=INT32_MAX,
  *                           bool weighted=False,             # <<<<<<<<<<<<<<
@@ -40050,7 +39107,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
  */
   bool __pyx_v_weighted = ((bool)0);
 
-  /* "pywrapfst.pyx":3792
+  /* "pywrapfst.pyx":3810
  *                           int32 max_length=INT32_MAX,
  *                           bool weighted=False,
  *                           bool remove_total_weight=False):             # <<<<<<<<<<<<<<
@@ -40089,18 +39146,18 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
     }
   }
 
-  /* "pywrapfst.pyx":3824
+  /* "pywrapfst.pyx":3842
  *   See also: `randequivalent`.
  *   """
  *   cdef fst.RandArcSelection ras = _get_rand_arc_selection(tostring(select))             # <<<<<<<<<<<<<<
  *   cdef unique_ptr[fst.RandGenOptions[fst.RandArcSelection]] opts
  *   opts.reset(new fst.RandGenOptions[fst.RandArcSelection](ras, max_length,
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_select, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3824, __pyx_L1_error)
-  __pyx_t_2 = __pyx_f_9pywrapfst__get_rand_arc_selection(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3824, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_select, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3842, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst__get_rand_arc_selection(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3842, __pyx_L1_error)
   __pyx_v_ras = __pyx_t_2;
 
-  /* "pywrapfst.pyx":3826
+  /* "pywrapfst.pyx":3844
  *   cdef fst.RandArcSelection ras = _get_rand_arc_selection(tostring(select))
  *   cdef unique_ptr[fst.RandGenOptions[fst.RandArcSelection]] opts
  *   opts.reset(new fst.RandGenOptions[fst.RandArcSelection](ras, max_length,             # <<<<<<<<<<<<<<
@@ -40109,7 +39166,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
  */
   __pyx_v_opts.reset(new fst::RandGenOptions<enum fst::script::RandArcSelection> (__pyx_v_ras, __pyx_v_max_length, __pyx_v_npath, __pyx_v_weighted, __pyx_v_remove_total_weight));
 
-  /* "pywrapfst.pyx":3830
+  /* "pywrapfst.pyx":3848
  *                                                           remove_total_weight))
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -40118,11 +39175,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3830, __pyx_L1_error)
+    __PYX_ERR(0, 3848, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":3831
+  /* "pywrapfst.pyx":3849
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   if seed == 0:             # <<<<<<<<<<<<<<
@@ -40132,7 +39189,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
   __pyx_t_3 = ((__pyx_v_seed == 0) != 0);
   if (__pyx_t_3) {
 
-    /* "pywrapfst.pyx":3832
+    /* "pywrapfst.pyx":3850
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   if seed == 0:
  *     seed = time(NULL) + getpid()             # <<<<<<<<<<<<<<
@@ -40141,7 +39198,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
  */
     __pyx_v_seed = (time(NULL) + getpid());
 
-    /* "pywrapfst.pyx":3831
+    /* "pywrapfst.pyx":3849
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   if seed == 0:             # <<<<<<<<<<<<<<
@@ -40150,7 +39207,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
  */
   }
 
-  /* "pywrapfst.pyx":3833
+  /* "pywrapfst.pyx":3851
  *   if seed == 0:
  *     seed = time(NULL) + getpid()
  *   fst.RandGen(deref(ifst._fst), tfst.get(), seed, deref(opts))             # <<<<<<<<<<<<<<
@@ -40159,11 +39216,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3833, __pyx_L1_error)
+    __PYX_ERR(0, 3851, __pyx_L1_error)
   }
   fst::script::RandGen((*__pyx_v_ifst->_fst), __pyx_v_tfst.get(), __pyx_v_seed, (*__pyx_v_opts));
 
-  /* "pywrapfst.pyx":3834
+  /* "pywrapfst.pyx":3852
  *     seed = time(NULL) + getpid()
  *   fst.RandGen(deref(ifst._fst), tfst.get(), seed, deref(opts))
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -40171,13 +39228,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_4 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3834, __pyx_L1_error)
+  __pyx_t_4 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3852, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_4);
   __pyx_t_4 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3786
+  /* "pywrapfst.pyx":3804
  * 
  * 
  * cpdef _MutableFst randgen(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -40197,9 +39254,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_randgen(struc
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_45randgen(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_44randgen[] = "\n  randgen(ifst, npath=1, seed=0, select=\"uniform\", max_length=2147483647,\n          weight=False, remove_total_weight=False)\n\n  Randomly generate successful paths in an FST.\n\n  This operation randomly generates a set of successful paths in the input FST.\n  This relies on a mechanism for selecting arcs, specified using the `select`\n  argument. The default selector, \"uniform\", randomly selects a transition\n  using a uniform distribution. The \"log_prob\" selector randomly selects a\n  transition w.r.t. the weights treated as negative log probabilities after\n  normalizing for the total weight leaving the state. In all cases, finality is\n  treated as a transition to a super-final state.\n\n  Args:\n    ifst: The input FST.\n    npath: The number of random paths to generate.\n    seed: An optional seed value for random path generation; if zero, the\n        current time and process ID is used.\n    select: A string matching a known random arc selection type; one of:\n        \"uniform\", \"log_prob\", \"fast_log_prob\".\n    max_length: The maximum length of each random path.\n    weighted: Should the output be weighted by path count?\n    remove_total_weight: Should the total weight be removed (ignored when\n        `weighted` is False)?\n\n  Returns:\n    An FST containing one or more random paths.\n\n  See also: `randequivalent`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_45randgen(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_47randgen(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_46randgen[] = "\n  randgen(ifst, npath=1, seed=0, select=\"uniform\", max_length=2147483647,\n          weighted=False, remove_total_weight=False)\n\n  Randomly generate successful paths in an FST.\n\n  This operation randomly generates a set of successful paths in the input FST.\n  This relies on a mechanism for selecting arcs, specified using the `select`\n  argument. The default selector, \"uniform\", randomly selects a transition\n  using a uniform distribution. The \"log_prob\" selector randomly selects a\n  transition w.r.t. the weights treated as negative log probabilities after\n  normalizing for the total weight leaving the state. In all cases, finality is\n  treated as a transition to a super-final state.\n\n  Args:\n    ifst: The input FST.\n    npath: The number of random paths to generate.\n    seed: An optional seed value for random path generation; if zero, the\n        current time and process ID is used.\n    select: A string matching a known random arc selection type; one of:\n        \"uniform\", \"log_prob\", \"fast_log_prob\".\n    max_length: The maximum length of each random path.\n    weighted: Should the output be weighted by path count?\n    remove_total_weight: Should the total weight be removed (ignored when\n        `weighted` is False)?\n\n  Returns:\n    An FST containing one or more random paths.\n\n  See also: `randequivalent`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_47randgen(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   __pyx_t_10basictypes_int32 __pyx_v_npath;
   time_t __pyx_v_seed;
@@ -40278,7 +39335,7 @@ static PyObject *__pyx_pw_9pywrapfst_45randgen(PyObject *__pyx_self, PyObject *_
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "randgen") < 0)) __PYX_ERR(0, 3786, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "randgen") < 0)) __PYX_ERR(0, 3804, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -40301,26 +39358,26 @@ static PyObject *__pyx_pw_9pywrapfst_45randgen(PyObject *__pyx_self, PyObject *_
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_npath = __Pyx_PyInt_As_int32_t(values[1]); if (unlikely((__pyx_v_npath == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3787, __pyx_L3_error)
+      __pyx_v_npath = __Pyx_PyInt_As_int32_t(values[1]); if (unlikely((__pyx_v_npath == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3805, __pyx_L3_error)
     } else {
       __pyx_v_npath = ((__pyx_t_10basictypes_int32)1);
     }
     if (values[2]) {
-      __pyx_v_seed = __Pyx_PyInt_As_time_t(values[2]); if (unlikely((__pyx_v_seed == ((time_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3788, __pyx_L3_error)
+      __pyx_v_seed = __Pyx_PyInt_As_time_t(values[2]); if (unlikely((__pyx_v_seed == ((time_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3806, __pyx_L3_error)
     } else {
       __pyx_v_seed = ((time_t)0);
     }
     __pyx_v_select = values[3];
     if (values[4]) {
-      __pyx_v_max_length = __Pyx_PyInt_As_int32_t(values[4]); if (unlikely((__pyx_v_max_length == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3790, __pyx_L3_error)
+      __pyx_v_max_length = __Pyx_PyInt_As_int32_t(values[4]); if (unlikely((__pyx_v_max_length == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3808, __pyx_L3_error)
     } else {
-      __pyx_v_max_length = __pyx_k__81;
+      __pyx_v_max_length = __pyx_k__45;
     }
     if (values[5]) {
-      __pyx_v_weighted = __Pyx_PyObject_IsTrue(values[5]); if (unlikely((__pyx_v_weighted == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3791, __pyx_L3_error)
+      __pyx_v_weighted = __Pyx_PyObject_IsTrue(values[5]); if (unlikely((__pyx_v_weighted == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3809, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3791
+      /* "pywrapfst.pyx":3809
  *                           select=b"uniform",
  *                           int32 max_length=INT32_MAX,
  *                           bool weighted=False,             # <<<<<<<<<<<<<<
@@ -40330,10 +39387,10 @@ static PyObject *__pyx_pw_9pywrapfst_45randgen(PyObject *__pyx_self, PyObject *_
       __pyx_v_weighted = ((bool)0);
     }
     if (values[6]) {
-      __pyx_v_remove_total_weight = __Pyx_PyObject_IsTrue(values[6]); if (unlikely((__pyx_v_remove_total_weight == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3792, __pyx_L3_error)
+      __pyx_v_remove_total_weight = __Pyx_PyObject_IsTrue(values[6]); if (unlikely((__pyx_v_remove_total_weight == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3810, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3792
+      /* "pywrapfst.pyx":3810
  *                           int32 max_length=INT32_MAX,
  *                           bool weighted=False,
  *                           bool remove_total_weight=False):             # <<<<<<<<<<<<<<
@@ -40345,16 +39402,16 @@ static PyObject *__pyx_pw_9pywrapfst_45randgen(PyObject *__pyx_self, PyObject *_
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("randgen", 0, 1, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3786, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("randgen", 0, 1, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3804, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.randgen", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3786, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_44randgen(__pyx_self, __pyx_v_ifst, __pyx_v_npath, __pyx_v_seed, __pyx_v_select, __pyx_v_max_length, __pyx_v_weighted, __pyx_v_remove_total_weight);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3804, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_46randgen(__pyx_self, __pyx_v_ifst, __pyx_v_npath, __pyx_v_seed, __pyx_v_select, __pyx_v_max_length, __pyx_v_weighted, __pyx_v_remove_total_weight);
 
-  /* "pywrapfst.pyx":3786
+  /* "pywrapfst.pyx":3804
  * 
  * 
  * cpdef _MutableFst randgen(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -40371,7 +39428,7 @@ static PyObject *__pyx_pw_9pywrapfst_45randgen(PyObject *__pyx_self, PyObject *_
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_44randgen(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, __pyx_t_10basictypes_int32 __pyx_v_npath, time_t __pyx_v_seed, PyObject *__pyx_v_select, __pyx_t_10basictypes_int32 __pyx_v_max_length, bool __pyx_v_weighted, bool __pyx_v_remove_total_weight) {
+static PyObject *__pyx_pf_9pywrapfst_46randgen(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, __pyx_t_10basictypes_int32 __pyx_v_npath, time_t __pyx_v_seed, PyObject *__pyx_v_select, __pyx_t_10basictypes_int32 __pyx_v_max_length, bool __pyx_v_weighted, bool __pyx_v_remove_total_weight) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -40385,7 +39442,7 @@ static PyObject *__pyx_pf_9pywrapfst_44randgen(CYTHON_UNUSED PyObject *__pyx_sel
   __pyx_t_2.max_length = __pyx_v_max_length;
   __pyx_t_2.remove_total_weight = __pyx_v_weighted;
   __pyx_t_2.weighted = __pyx_v_remove_total_weight;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_randgen(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3786, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_randgen(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3804, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -40402,7 +39459,7 @@ static PyObject *__pyx_pf_9pywrapfst_44randgen(CYTHON_UNUSED PyObject *__pyx_sel
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3837
+/* "pywrapfst.pyx":3855
  * 
  * 
  * cpdef _MutableFst replace(pairs,             # <<<<<<<<<<<<<<
@@ -40410,12 +39467,12 @@ static PyObject *__pyx_pf_9pywrapfst_44randgen(CYTHON_UNUSED PyObject *__pyx_sel
  *                           return_arc_labeling=b"neither",
  */
 
-static PyObject *__pyx_pw_9pywrapfst_47replace(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_49replace(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObject *__pyx_v_pairs, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_replace *__pyx_optional_args) {
   PyObject *__pyx_v_call_arc_labeling = ((PyObject *)__pyx_n_b_input);
   PyObject *__pyx_v_return_arc_labeling = ((PyObject *)__pyx_n_b_neither);
 
-  /* "pywrapfst.pyx":3840
+  /* "pywrapfst.pyx":3858
  *                           call_arc_labeling=b"input",
  *                           return_arc_labeling=b"neither",
  *                           bool epsilon_on_replace=False,             # <<<<<<<<<<<<<<
@@ -40463,26 +39520,26 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
     }
   }
 
-  /* "pywrapfst.pyx":3882
+  /* "pywrapfst.pyx":3900
  *   cdef int64 label
  *   cdef _Fst ifst
  *   it = iter(pairs)             # <<<<<<<<<<<<<<
  *   (root_label, ifst) = next(it)
  *   _pairs.push_back(fst.LabelFstClassPair(root_label, ifst._fst.get()))
  */
-  __pyx_t_1 = PyObject_GetIter(__pyx_v_pairs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3882, __pyx_L1_error)
+  __pyx_t_1 = PyObject_GetIter(__pyx_v_pairs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3900, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_it = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":3883
+  /* "pywrapfst.pyx":3901
  *   cdef _Fst ifst
  *   it = iter(pairs)
  *   (root_label, ifst) = next(it)             # <<<<<<<<<<<<<<
  *   _pairs.push_back(fst.LabelFstClassPair(root_label, ifst._fst.get()))
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  */
-  __pyx_t_1 = __Pyx_PyIter_Next(__pyx_v_it); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3883, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyIter_Next(__pyx_v_it); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3901, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
     PyObject* sequence = __pyx_t_1;
@@ -40490,7 +39547,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
     if (unlikely(size != 2)) {
       if (size > 2) __Pyx_RaiseTooManyValuesError(2);
       else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-      __PYX_ERR(0, 3883, __pyx_L1_error)
+      __PYX_ERR(0, 3901, __pyx_L1_error)
     }
     #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
     if (likely(PyTuple_CheckExact(sequence))) {
@@ -40503,15 +39560,15 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
     __Pyx_INCREF(__pyx_t_2);
     __Pyx_INCREF(__pyx_t_3);
     #else
-    __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3883, __pyx_L1_error)
+    __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3901, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3883, __pyx_L1_error)
+    __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3901, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
     #endif
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   } else {
     Py_ssize_t index = -1;
-    __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3883, __pyx_L1_error)
+    __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3901, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __pyx_t_5 = Py_TYPE(__pyx_t_4)->tp_iternext;
@@ -40519,7 +39576,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
     __Pyx_GOTREF(__pyx_t_2);
     index = 1; __pyx_t_3 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_3)) goto __pyx_L3_unpacking_failed;
     __Pyx_GOTREF(__pyx_t_3);
-    if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_4), 2) < 0) __PYX_ERR(0, 3883, __pyx_L1_error)
+    if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_4), 2) < 0) __PYX_ERR(0, 3901, __pyx_L1_error)
     __pyx_t_5 = NULL;
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     goto __pyx_L4_unpacking_done;
@@ -40527,17 +39584,17 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __pyx_t_5 = NULL;
     if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-    __PYX_ERR(0, 3883, __pyx_L1_error)
+    __PYX_ERR(0, 3901, __pyx_L1_error)
     __pyx_L4_unpacking_done:;
   }
-  __pyx_t_6 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_6 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3883, __pyx_L1_error)
+  __pyx_t_6 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_6 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3901, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 3883, __pyx_L1_error)
+  if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 3901, __pyx_L1_error)
   __pyx_v_root_label = __pyx_t_6;
   __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_3);
   __pyx_t_3 = 0;
 
-  /* "pywrapfst.pyx":3884
+  /* "pywrapfst.pyx":3902
  *   it = iter(pairs)
  *   (root_label, ifst) = next(it)
  *   _pairs.push_back(fst.LabelFstClassPair(root_label, ifst._fst.get()))             # <<<<<<<<<<<<<<
@@ -40546,22 +39603,22 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3884, __pyx_L1_error)
+    __PYX_ERR(0, 3902, __pyx_L1_error)
   }
   try {
     __pyx_t_7 = __pyx_t_3fst_LabelFstClassPair(__pyx_v_root_label, __pyx_v_ifst->_fst.get());
   } catch(...) {
     __Pyx_CppExn2PyErr();
-    __PYX_ERR(0, 3884, __pyx_L1_error)
+    __PYX_ERR(0, 3902, __pyx_L1_error)
   }
   try {
     __pyx_v__pairs.push_back(__pyx_t_7);
   } catch(...) {
     __Pyx_CppExn2PyErr();
-    __PYX_ERR(0, 3884, __pyx_L1_error)
+    __PYX_ERR(0, 3902, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":3886
+  /* "pywrapfst.pyx":3904
  *   _pairs.push_back(fst.LabelFstClassPair(root_label, ifst._fst.get()))
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -40570,11 +39627,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3886, __pyx_L1_error)
+    __PYX_ERR(0, 3904, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":3887
+  /* "pywrapfst.pyx":3905
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   for (label, ifst) in it:             # <<<<<<<<<<<<<<
@@ -40585,26 +39642,26 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
     __pyx_t_1 = __pyx_v_it; __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
     __pyx_t_9 = NULL;
   } else {
-    __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_it); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3887, __pyx_L1_error)
+    __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_it); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3905, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3887, __pyx_L1_error)
+    __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3905, __pyx_L1_error)
   }
   for (;;) {
     if (likely(!__pyx_t_9)) {
       if (likely(PyList_CheckExact(__pyx_t_1))) {
         if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
         #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 3887, __pyx_L1_error)
+        __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 3905, __pyx_L1_error)
         #else
-        __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3887, __pyx_L1_error)
+        __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3905, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_3);
         #endif
       } else {
         if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
         #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 3887, __pyx_L1_error)
+        __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 3905, __pyx_L1_error)
         #else
-        __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3887, __pyx_L1_error)
+        __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3905, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_3);
         #endif
       }
@@ -40614,7 +39671,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
         PyObject* exc_type = PyErr_Occurred();
         if (exc_type) {
           if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(0, 3887, __pyx_L1_error)
+          else __PYX_ERR(0, 3905, __pyx_L1_error)
         }
         break;
       }
@@ -40626,7 +39683,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
       if (unlikely(size != 2)) {
         if (size > 2) __Pyx_RaiseTooManyValuesError(2);
         else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        __PYX_ERR(0, 3887, __pyx_L1_error)
+        __PYX_ERR(0, 3905, __pyx_L1_error)
       }
       #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
       if (likely(PyTuple_CheckExact(sequence))) {
@@ -40639,15 +39696,15 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
       __Pyx_INCREF(__pyx_t_2);
       __Pyx_INCREF(__pyx_t_4);
       #else
-      __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3887, __pyx_L1_error)
+      __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3905, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3887, __pyx_L1_error)
+      __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3905, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_4);
       #endif
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     } else {
       Py_ssize_t index = -1;
-      __pyx_t_10 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 3887, __pyx_L1_error)
+      __pyx_t_10 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 3905, __pyx_L1_error)
       __Pyx_GOTREF(__pyx_t_10);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __pyx_t_5 = Py_TYPE(__pyx_t_10)->tp_iternext;
@@ -40655,7 +39712,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
       __Pyx_GOTREF(__pyx_t_2);
       index = 1; __pyx_t_4 = __pyx_t_5(__pyx_t_10); if (unlikely(!__pyx_t_4)) goto __pyx_L7_unpacking_failed;
       __Pyx_GOTREF(__pyx_t_4);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_10), 2) < 0) __PYX_ERR(0, 3887, __pyx_L1_error)
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_10), 2) < 0) __PYX_ERR(0, 3905, __pyx_L1_error)
       __pyx_t_5 = NULL;
       __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
       goto __pyx_L8_unpacking_done;
@@ -40663,17 +39720,17 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
       __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
       __pyx_t_5 = NULL;
       if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      __PYX_ERR(0, 3887, __pyx_L1_error)
+      __PYX_ERR(0, 3905, __pyx_L1_error)
       __pyx_L8_unpacking_done:;
     }
-    __pyx_t_6 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_6 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3887, __pyx_L1_error)
+    __pyx_t_6 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_6 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3905, __pyx_L1_error)
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 3887, __pyx_L1_error)
+    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 3905, __pyx_L1_error)
     __pyx_v_label = __pyx_t_6;
     __Pyx_DECREF_SET(__pyx_v_ifst, ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_4));
     __pyx_t_4 = 0;
 
-    /* "pywrapfst.pyx":3888
+    /* "pywrapfst.pyx":3906
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   for (label, ifst) in it:
  *     _pairs.push_back(fst.LabelFstClassPair(label, ifst._fst.get()))             # <<<<<<<<<<<<<<
@@ -40682,22 +39739,22 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
  */
     if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-      __PYX_ERR(0, 3888, __pyx_L1_error)
+      __PYX_ERR(0, 3906, __pyx_L1_error)
     }
     try {
       __pyx_t_7 = __pyx_t_3fst_LabelFstClassPair(__pyx_v_label, __pyx_v_ifst->_fst.get());
     } catch(...) {
       __Pyx_CppExn2PyErr();
-      __PYX_ERR(0, 3888, __pyx_L1_error)
+      __PYX_ERR(0, 3906, __pyx_L1_error)
     }
     try {
       __pyx_v__pairs.push_back(__pyx_t_7);
     } catch(...) {
       __Pyx_CppExn2PyErr();
-      __PYX_ERR(0, 3888, __pyx_L1_error)
+      __PYX_ERR(0, 3906, __pyx_L1_error)
     }
 
-    /* "pywrapfst.pyx":3887
+    /* "pywrapfst.pyx":3905
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   for (label, ifst) in it:             # <<<<<<<<<<<<<<
@@ -40707,45 +39764,45 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":3890
+  /* "pywrapfst.pyx":3908
  *     _pairs.push_back(fst.LabelFstClassPair(label, ifst._fst.get()))
  *   cdef fst.ReplaceLabelType cal = _get_replace_label_type(
  *       tostring(call_arc_labeling), epsilon_on_replace)             # <<<<<<<<<<<<<<
  *   cdef fst.ReplaceLabelType ral = _get_replace_label_type(
  *       tostring(return_arc_labeling), epsilon_on_replace)
  */
-  __pyx_t_11 = __pyx_f_9pywrapfst_tostring(__pyx_v_call_arc_labeling, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3890, __pyx_L1_error)
+  __pyx_t_11 = __pyx_f_9pywrapfst_tostring(__pyx_v_call_arc_labeling, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3908, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":3889
+  /* "pywrapfst.pyx":3907
  *   for (label, ifst) in it:
  *     _pairs.push_back(fst.LabelFstClassPair(label, ifst._fst.get()))
  *   cdef fst.ReplaceLabelType cal = _get_replace_label_type(             # <<<<<<<<<<<<<<
  *       tostring(call_arc_labeling), epsilon_on_replace)
  *   cdef fst.ReplaceLabelType ral = _get_replace_label_type(
  */
-  __pyx_t_12 = __pyx_f_9pywrapfst__get_replace_label_type(__pyx_t_11, __pyx_v_epsilon_on_replace); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3889, __pyx_L1_error)
+  __pyx_t_12 = __pyx_f_9pywrapfst__get_replace_label_type(__pyx_t_11, __pyx_v_epsilon_on_replace); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3907, __pyx_L1_error)
   __pyx_v_cal = __pyx_t_12;
 
-  /* "pywrapfst.pyx":3892
+  /* "pywrapfst.pyx":3910
  *       tostring(call_arc_labeling), epsilon_on_replace)
  *   cdef fst.ReplaceLabelType ral = _get_replace_label_type(
  *       tostring(return_arc_labeling), epsilon_on_replace)             # <<<<<<<<<<<<<<
  *   cdef unique_ptr[fst.ReplaceOptions] opts
  *   opts.reset(new fst.ReplaceOptions(root_label, cal, ral, return_label))
  */
-  __pyx_t_11 = __pyx_f_9pywrapfst_tostring(__pyx_v_return_arc_labeling, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3892, __pyx_L1_error)
+  __pyx_t_11 = __pyx_f_9pywrapfst_tostring(__pyx_v_return_arc_labeling, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3910, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":3891
+  /* "pywrapfst.pyx":3909
  *   cdef fst.ReplaceLabelType cal = _get_replace_label_type(
  *       tostring(call_arc_labeling), epsilon_on_replace)
  *   cdef fst.ReplaceLabelType ral = _get_replace_label_type(             # <<<<<<<<<<<<<<
  *       tostring(return_arc_labeling), epsilon_on_replace)
  *   cdef unique_ptr[fst.ReplaceOptions] opts
  */
-  __pyx_t_12 = __pyx_f_9pywrapfst__get_replace_label_type(__pyx_t_11, __pyx_v_epsilon_on_replace); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3891, __pyx_L1_error)
+  __pyx_t_12 = __pyx_f_9pywrapfst__get_replace_label_type(__pyx_t_11, __pyx_v_epsilon_on_replace); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3909, __pyx_L1_error)
   __pyx_v_ral = __pyx_t_12;
 
-  /* "pywrapfst.pyx":3894
+  /* "pywrapfst.pyx":3912
  *       tostring(return_arc_labeling), epsilon_on_replace)
  *   cdef unique_ptr[fst.ReplaceOptions] opts
  *   opts.reset(new fst.ReplaceOptions(root_label, cal, ral, return_label))             # <<<<<<<<<<<<<<
@@ -40754,7 +39811,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
  */
   __pyx_v_opts.reset(new fst::script::ReplaceOptions(__pyx_v_root_label, __pyx_v_cal, __pyx_v_ral, __pyx_v_return_label));
 
-  /* "pywrapfst.pyx":3895
+  /* "pywrapfst.pyx":3913
  *   cdef unique_ptr[fst.ReplaceOptions] opts
  *   opts.reset(new fst.ReplaceOptions(root_label, cal, ral, return_label))
  *   fst.Replace(_pairs, tfst.get(), deref(opts))             # <<<<<<<<<<<<<<
@@ -40763,7 +39820,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
  */
   fst::script::Replace(__pyx_v__pairs, __pyx_v_tfst.get(), (*__pyx_v_opts));
 
-  /* "pywrapfst.pyx":3896
+  /* "pywrapfst.pyx":3914
  *   opts.reset(new fst.ReplaceOptions(root_label, cal, ral, return_label))
  *   fst.Replace(_pairs, tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -40771,13 +39828,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3896, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3914, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3837
+  /* "pywrapfst.pyx":3855
  * 
  * 
  * cpdef _MutableFst replace(pairs,             # <<<<<<<<<<<<<<
@@ -40803,9 +39860,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_replace(PyObj
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_47replace(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_46replace[] = "\n  replace(pairs, call_arc_labeling=\"input\", return_arc_labeling=\"neither\",\n          epsilon_on_replace=False, return_label=0)\n\n  Recursively replaces arcs in the FST with other FST(s).\n\n  This operation performs the dynamic replacement of arcs in one FST with\n  another FST, allowing the definition of FSTs analogous to RTNs. It takes as\n  input a set of pairs of a set of pairs formed by a non-terminal label and\n  its corresponding FST, and a label identifying the root FST in that set.\n  The resulting FST is obtained by taking the root FST and recursively replacing\n  each arc having a nonterminal as output label by its corresponding FST. More\n  precisely, an arc from state s to state d with (nonterminal) output label n in\n  this FST is replaced by redirecting this \"call\" arc to the initial state of a\n  copy F of the FST for n, and adding \"return\" arcs from each final state of F\n  to d. Optional arguments control how the call and return arcs are labeled; by\n  default, the only non-epsilon label is placed on the call arc.\n\n  Args:\n\n    pairs: An iterable of (nonterminal label, FST) pairs, where the former is an\n        unsigned integer and the latter is an Fst instance.\n    call_arc_labeling: A string indicating which call arc labels should be\n        non-epsilon. One of: \"input\" (default), \"output\", \"both\", \"neither\".\n        This value is set to \"neither\" if epsilon_on_replace is True.\n    return_arc_labeling: A string indicating which return arc labels should be\n        non-epsilon. One of: \"input\", \"output\", \"both\", \"neither\" (default).\n        This value is set to \"neither\" if epsilon_on_replace is True.\n    epsilon_on_replace: Should call and return arcs be epsilon arcs? If True,\n        this effectively overrides call_arc_labeling and return_arc_labeling,\n        setting both to \"neither\".\n    return_label: The integer label for return arcs.\n\n  Returns:\n    An FST resulting from expanding the input"" RTN.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_47replace(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_49replace(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_48replace[] = "\n  replace(pairs, call_arc_labeling=\"input\", return_arc_labeling=\"neither\",\n          epsilon_on_replace=False, return_label=0)\n\n  Recursively replaces arcs in the FST with other FST(s).\n\n  This operation performs the dynamic replacement of arcs in one FST with\n  another FST, allowing the definition of FSTs analogous to RTNs. It takes as\n  input a set of pairs of a set of pairs formed by a non-terminal label and\n  its corresponding FST, and a label identifying the root FST in that set.\n  The resulting FST is obtained by taking the root FST and recursively replacing\n  each arc having a nonterminal as output label by its corresponding FST. More\n  precisely, an arc from state s to state d with (nonterminal) output label n in\n  this FST is replaced by redirecting this \"call\" arc to the initial state of a\n  copy F of the FST for n, and adding \"return\" arcs from each final state of F\n  to d. Optional arguments control how the call and return arcs are labeled; by\n  default, the only non-epsilon label is placed on the call arc.\n\n  Args:\n\n    pairs: An iterable of (nonterminal label, FST) pairs, where the former is an\n        unsigned integer and the latter is an Fst instance.\n    call_arc_labeling: A string indicating which call arc labels should be\n        non-epsilon. One of: \"input\" (default), \"output\", \"both\", \"neither\".\n        This value is set to \"neither\" if epsilon_on_replace is True.\n    return_arc_labeling: A string indicating which return arc labels should be\n        non-epsilon. One of: \"input\", \"output\", \"both\", \"neither\" (default).\n        This value is set to \"neither\" if epsilon_on_replace is True.\n    epsilon_on_replace: Should call and return arcs be epsilon arcs? If True,\n        this effectively overrides call_arc_labeling and return_arc_labeling,\n        setting both to \"neither\".\n    return_label: The integer label for return arcs.\n\n  Returns:\n    An FST resulting from expanding the input"" RTN.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_49replace(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_pairs = 0;
   PyObject *__pyx_v_call_arc_labeling = 0;
   PyObject *__pyx_v_return_arc_labeling = 0;
@@ -40867,7 +39924,7 @@ static PyObject *__pyx_pw_9pywrapfst_47replace(PyObject *__pyx_self, PyObject *_
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "replace") < 0)) __PYX_ERR(0, 3837, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "replace") < 0)) __PYX_ERR(0, 3855, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -40888,10 +39945,10 @@ static PyObject *__pyx_pw_9pywrapfst_47replace(PyObject *__pyx_self, PyObject *_
     __pyx_v_call_arc_labeling = values[1];
     __pyx_v_return_arc_labeling = values[2];
     if (values[3]) {
-      __pyx_v_epsilon_on_replace = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_epsilon_on_replace == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3840, __pyx_L3_error)
+      __pyx_v_epsilon_on_replace = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_epsilon_on_replace == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3858, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3840
+      /* "pywrapfst.pyx":3858
  *                           call_arc_labeling=b"input",
  *                           return_arc_labeling=b"neither",
  *                           bool epsilon_on_replace=False,             # <<<<<<<<<<<<<<
@@ -40901,22 +39958,22 @@ static PyObject *__pyx_pw_9pywrapfst_47replace(PyObject *__pyx_self, PyObject *_
       __pyx_v_epsilon_on_replace = ((bool)0);
     }
     if (values[4]) {
-      __pyx_v_return_label = __Pyx_PyInt_As_int64_t(values[4]); if (unlikely((__pyx_v_return_label == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3841, __pyx_L3_error)
+      __pyx_v_return_label = __Pyx_PyInt_As_int64_t(values[4]); if (unlikely((__pyx_v_return_label == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3859, __pyx_L3_error)
     } else {
       __pyx_v_return_label = ((__pyx_t_10basictypes_int64)0);
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("replace", 0, 1, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3837, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("replace", 0, 1, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3855, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.replace", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9pywrapfst_46replace(__pyx_self, __pyx_v_pairs, __pyx_v_call_arc_labeling, __pyx_v_return_arc_labeling, __pyx_v_epsilon_on_replace, __pyx_v_return_label);
+  __pyx_r = __pyx_pf_9pywrapfst_48replace(__pyx_self, __pyx_v_pairs, __pyx_v_call_arc_labeling, __pyx_v_return_arc_labeling, __pyx_v_epsilon_on_replace, __pyx_v_return_label);
 
-  /* "pywrapfst.pyx":3837
+  /* "pywrapfst.pyx":3855
  * 
  * 
  * cpdef _MutableFst replace(pairs,             # <<<<<<<<<<<<<<
@@ -40929,7 +39986,7 @@ static PyObject *__pyx_pw_9pywrapfst_47replace(PyObject *__pyx_self, PyObject *_
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_46replace(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_pairs, PyObject *__pyx_v_call_arc_labeling, PyObject *__pyx_v_return_arc_labeling, bool __pyx_v_epsilon_on_replace, __pyx_t_10basictypes_int64 __pyx_v_return_label) {
+static PyObject *__pyx_pf_9pywrapfst_48replace(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_pairs, PyObject *__pyx_v_call_arc_labeling, PyObject *__pyx_v_return_arc_labeling, bool __pyx_v_epsilon_on_replace, __pyx_t_10basictypes_int64 __pyx_v_return_label) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -40941,7 +39998,7 @@ static PyObject *__pyx_pf_9pywrapfst_46replace(CYTHON_UNUSED PyObject *__pyx_sel
   __pyx_t_2.return_arc_labeling = __pyx_v_return_arc_labeling;
   __pyx_t_2.epsilon_on_replace = __pyx_v_epsilon_on_replace;
   __pyx_t_2.return_label = __pyx_v_return_label;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_replace(__pyx_v_pairs, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3837, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_replace(__pyx_v_pairs, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3855, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -40958,7 +40015,7 @@ static PyObject *__pyx_pf_9pywrapfst_46replace(CYTHON_UNUSED PyObject *__pyx_sel
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3899
+/* "pywrapfst.pyx":3917
  * 
  * 
  * cpdef _MutableFst reverse(_Fst ifst, bool require_superinitial=True):             # <<<<<<<<<<<<<<
@@ -40966,7 +40023,7 @@ static PyObject *__pyx_pf_9pywrapfst_46replace(CYTHON_UNUSED PyObject *__pyx_sel
  *   reverse(ifst, require_superinitial=True)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_49reverse(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_51reverse(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_reverse(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_reverse *__pyx_optional_args) {
   bool __pyx_v_require_superinitial = ((bool)1);
   std::unique_ptr<fst::script::VectorFstClass>  __pyx_v_tfst;
@@ -40980,7 +40037,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_reverse(struc
     }
   }
 
-  /* "pywrapfst.pyx":3919
+  /* "pywrapfst.pyx":3937
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -40989,11 +40046,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_reverse(struc
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 3919, __pyx_L1_error)
+    __PYX_ERR(0, 3937, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":3920
+  /* "pywrapfst.pyx":3938
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   fst.Reverse(deref(ifst._fst), tfst.get(), require_superinitial)             # <<<<<<<<<<<<<<
@@ -41002,11 +40059,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_reverse(struc
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 3920, __pyx_L1_error)
+    __PYX_ERR(0, 3938, __pyx_L1_error)
   }
   fst::script::Reverse((*__pyx_v_ifst->_fst), __pyx_v_tfst.get(), __pyx_v_require_superinitial);
 
-  /* "pywrapfst.pyx":3921
+  /* "pywrapfst.pyx":3939
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   fst.Reverse(deref(ifst._fst), tfst.get(), require_superinitial)
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -41014,13 +40071,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_reverse(struc
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3921, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3939, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3899
+  /* "pywrapfst.pyx":3917
  * 
  * 
  * cpdef _MutableFst reverse(_Fst ifst, bool require_superinitial=True):             # <<<<<<<<<<<<<<
@@ -41040,9 +40097,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_reverse(struc
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_49reverse(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_48reverse[] = "\n  reverse(ifst, require_superinitial=True)\n\n  Constructively reverses an FST's transduction.\n\n  This operation reverses an FST. If A transduces string x to y with weight a,\n  then the reverse of A transduces the reverse of x to the reverse of y with\n  weight a.Reverse(). (Typically, a = a.Reverse() and Arc = RevArc, e.g.,\n  TropicalWeight and LogWeight.) In general, e.g., when the weights only form a\n  left or right semiring, the output arc type must match the input arc type.\n\n  Args:\n    ifst: The input FST.\n    require_superinitial: Should a superinitial state be created?\n\n  Returns:\n    A reversed FST.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_49reverse(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_51reverse(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_50reverse[] = "\n  reverse(ifst, require_superinitial=True)\n\n  Constructively reverses an FST's transduction.\n\n  This operation reverses an FST. If A transduces string x to y with weight a,\n  then the reverse of A transduces the reverse of x to the reverse of y with\n  weight a.Reverse(). (Typically, a = a.Reverse() and Arc = RevArc, e.g.,\n  TropicalWeight and LogWeight.) In general, e.g., when the weights only form a\n  left or right semiring, the output arc type must match the input arc type.\n\n  Args:\n    ifst: The input FST.\n    require_superinitial: Should a superinitial state be created?\n\n  Returns:\n    A reversed FST.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_51reverse(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   bool __pyx_v_require_superinitial;
   PyObject *__pyx_r = 0;
@@ -41075,7 +40132,7 @@ static PyObject *__pyx_pw_9pywrapfst_49reverse(PyObject *__pyx_self, PyObject *_
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "reverse") < 0)) __PYX_ERR(0, 3899, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "reverse") < 0)) __PYX_ERR(0, 3917, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -41088,21 +40145,21 @@ static PyObject *__pyx_pw_9pywrapfst_49reverse(PyObject *__pyx_self, PyObject *_
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_require_superinitial = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_require_superinitial == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3899, __pyx_L3_error)
+      __pyx_v_require_superinitial = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_require_superinitial == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3917, __pyx_L3_error)
     } else {
       __pyx_v_require_superinitial = ((bool)1);
     }
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("reverse", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3899, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("reverse", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3917, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.reverse", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3899, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_48reverse(__pyx_self, __pyx_v_ifst, __pyx_v_require_superinitial);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3917, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_50reverse(__pyx_self, __pyx_v_ifst, __pyx_v_require_superinitial);
 
   /* function exit code */
   goto __pyx_L0;
@@ -41113,7 +40170,7 @@ static PyObject *__pyx_pw_9pywrapfst_49reverse(PyObject *__pyx_self, PyObject *_
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_48reverse(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, bool __pyx_v_require_superinitial) {
+static PyObject *__pyx_pf_9pywrapfst_50reverse(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, bool __pyx_v_require_superinitial) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -41122,7 +40179,7 @@ static PyObject *__pyx_pf_9pywrapfst_48reverse(CYTHON_UNUSED PyObject *__pyx_sel
   __Pyx_XDECREF(__pyx_r);
   __pyx_t_2.__pyx_n = 1;
   __pyx_t_2.require_superinitial = __pyx_v_require_superinitial;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_reverse(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3899, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_reverse(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3917, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -41139,7 +40196,7 @@ static PyObject *__pyx_pf_9pywrapfst_48reverse(CYTHON_UNUSED PyObject *__pyx_sel
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3927
+/* "pywrapfst.pyx":3945
  * 
  * 
  * cdef vector[fst.WeightClass] *_shortestdistance(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -41148,11 +40205,11 @@ static PyObject *__pyx_pf_9pywrapfst_48reverse(CYTHON_UNUSED PyObject *__pyx_sel
  */
 
 static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdistance(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, struct __pyx_opt_args_9pywrapfst__shortestdistance *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__82;
-  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__83;
+  float __pyx_v_delta = __pyx_k__46;
+  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__47;
   PyObject *__pyx_v_queue_type = ((PyObject *)__pyx_n_b_auto);
 
-  /* "pywrapfst.pyx":3931
+  /* "pywrapfst.pyx":3949
  *                                                 int64 nstate=fst.kNoStateId,
  *                                                 queue_type=b"auto",
  *                                                 bool reverse=False) except *:             # <<<<<<<<<<<<<<
@@ -41184,7 +40241,7 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
     }
   }
 
-  /* "pywrapfst.pyx":3933
+  /* "pywrapfst.pyx":3951
  *                                                 bool reverse=False) except *:
  *   cdef unique_ptr[vector[fst.WeightClass]] distance
  *   distance.reset(new vector[fst.WeightClass]())             # <<<<<<<<<<<<<<
@@ -41195,11 +40252,11 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
     __pyx_t_1 = new std::vector<fst::script::WeightClass> ();
   } catch(...) {
     __Pyx_CppExn2PyErr();
-    __PYX_ERR(0, 3933, __pyx_L1_error)
+    __PYX_ERR(0, 3951, __pyx_L1_error)
   }
   __pyx_v_distance.reset(__pyx_t_1);
 
-  /* "pywrapfst.pyx":3937
+  /* "pywrapfst.pyx":3955
  *   # not be used in all cases.
  *   cdef unique_ptr[fst.ShortestDistanceOptions] opts
  *   if reverse:             # <<<<<<<<<<<<<<
@@ -41209,7 +40266,7 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
   __pyx_t_2 = (__pyx_v_reverse != 0);
   if (__pyx_t_2) {
 
-    /* "pywrapfst.pyx":3940
+    /* "pywrapfst.pyx":3958
  *     # Only the simpler signature supports shortest distance to final states;
  *     # `nstate` and `queue_type` arguments are ignored.
  *     fst.ShortestDistance(deref(ifst._fst), distance.get(), True, delta)             # <<<<<<<<<<<<<<
@@ -41218,11 +40275,11 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
  */
     if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-      __PYX_ERR(0, 3940, __pyx_L1_error)
+      __PYX_ERR(0, 3958, __pyx_L1_error)
     }
     fst::script::ShortestDistance((*__pyx_v_ifst->_fst), __pyx_v_distance.get(), 1, __pyx_v_delta);
 
-    /* "pywrapfst.pyx":3937
+    /* "pywrapfst.pyx":3955
  *   # not be used in all cases.
  *   cdef unique_ptr[fst.ShortestDistanceOptions] opts
  *   if reverse:             # <<<<<<<<<<<<<<
@@ -41232,7 +40289,7 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
     goto __pyx_L3;
   }
 
-  /* "pywrapfst.pyx":3942
+  /* "pywrapfst.pyx":3960
  *     fst.ShortestDistance(deref(ifst._fst), distance.get(), True, delta)
  *   else:
  *     opts.reset(new fst.ShortestDistanceOptions(             # <<<<<<<<<<<<<<
@@ -41241,17 +40298,17 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
  */
   /*else*/ {
 
-    /* "pywrapfst.pyx":3943
+    /* "pywrapfst.pyx":3961
  *   else:
  *     opts.reset(new fst.ShortestDistanceOptions(
  *         _get_queue_type(tostring(queue_type)), fst.ANY_ARC_FILTER, nstate,             # <<<<<<<<<<<<<<
  *         delta))
  *     fst.ShortestDistance(deref(ifst._fst), distance.get(), deref(opts))
  */
-    __pyx_t_3 = __pyx_f_9pywrapfst_tostring(__pyx_v_queue_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3943, __pyx_L1_error)
-    __pyx_t_4 = __pyx_f_9pywrapfst__get_queue_type(__pyx_t_3); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3943, __pyx_L1_error)
+    __pyx_t_3 = __pyx_f_9pywrapfst_tostring(__pyx_v_queue_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3961, __pyx_L1_error)
+    __pyx_t_4 = __pyx_f_9pywrapfst__get_queue_type(__pyx_t_3); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3961, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":3942
+    /* "pywrapfst.pyx":3960
  *     fst.ShortestDistance(deref(ifst._fst), distance.get(), True, delta)
  *   else:
  *     opts.reset(new fst.ShortestDistanceOptions(             # <<<<<<<<<<<<<<
@@ -41260,7 +40317,7 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
  */
     __pyx_v_opts.reset(new fst::script::ShortestDistanceOptions(__pyx_t_4, fst::script::ANY_ARC_FILTER, __pyx_v_nstate, __pyx_v_delta));
 
-    /* "pywrapfst.pyx":3945
+    /* "pywrapfst.pyx":3963
  *         _get_queue_type(tostring(queue_type)), fst.ANY_ARC_FILTER, nstate,
  *         delta))
  *     fst.ShortestDistance(deref(ifst._fst), distance.get(), deref(opts))             # <<<<<<<<<<<<<<
@@ -41269,13 +40326,13 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
  */
     if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-      __PYX_ERR(0, 3945, __pyx_L1_error)
+      __PYX_ERR(0, 3963, __pyx_L1_error)
     }
     fst::script::ShortestDistance((*__pyx_v_ifst->_fst), __pyx_v_distance.get(), (*__pyx_v_opts));
   }
   __pyx_L3:;
 
-  /* "pywrapfst.pyx":3946
+  /* "pywrapfst.pyx":3964
  *         delta))
  *     fst.ShortestDistance(deref(ifst._fst), distance.get(), deref(opts))
  *   return distance.release()             # <<<<<<<<<<<<<<
@@ -41285,7 +40342,7 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
   __pyx_r = __pyx_v_distance.release();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3927
+  /* "pywrapfst.pyx":3945
  * 
  * 
  * cdef vector[fst.WeightClass] *_shortestdistance(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -41302,7 +40359,7 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3949
+/* "pywrapfst.pyx":3967
  * 
  * 
  * def shortestdistance(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -41311,10 +40368,10 @@ static std::vector<fst::script::WeightClass>  *__pyx_f_9pywrapfst__shortestdista
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_51shortestdistance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_50shortestdistance[] = "\n  shortestdistance(ifst, delta=1e-6, nstate=NO_STATE_ID,\n                   queue_type=\"auto\", reverse=False)\n\n  Compute the shortest distance from the initial or final state.\n\n  This operation computes the shortest distance from the initial state (when\n  `reverse` is False) or from every state to the final state (when `reverse` is\n  True). The shortest distance from p to q is the \\otimes-sum of the weights of\n  all the paths between p and q. The weights must be right (if `reverse` is\n  False) or left (if `reverse` is True) distributive, and k-closed (i.e., 1\n  \\otimes x \\otimes x^2 \\otimes ... \\otimes x^{k + 1} = 1 \\otimes x \\otimes x^2\n  \\otimes ... \\otimes x^k; e.g., TropicalWeight).\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    nstate: State number threshold (ignored if `reverse` is True).\n    queue_type: A string matching a known queue type; one of: \"auto\", \"fifo\",\n        \"lifo\", \"shortest\", \"state\", \"top\" (ignored if `reverse` is True).\n    reverse: Should the reverse distance (from each state to the final state)\n        be computed?\n\n  Returns:\n    A list of Weight objects representing the shortest distance for each state.\n  ";
-static PyMethodDef __pyx_mdef_9pywrapfst_51shortestdistance = {"shortestdistance", (PyCFunction)__pyx_pw_9pywrapfst_51shortestdistance, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_50shortestdistance};
-static PyObject *__pyx_pw_9pywrapfst_51shortestdistance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_53shortestdistance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_52shortestdistance[] = "\n  shortestdistance(ifst, delta=1e-6, nstate=NO_STATE_ID,\n                   queue_type=\"auto\", reverse=False)\n\n  Compute the shortest distance from the initial or final state.\n\n  This operation computes the shortest distance from the initial state (when\n  `reverse` is False) or from every state to the final state (when `reverse` is\n  True). The shortest distance from p to q is the \\otimes-sum of the weights of\n  all the paths between p and q. The weights must be right (if `reverse` is\n  False) or left (if `reverse` is True) distributive, and k-closed (i.e., 1\n  \\otimes x \\otimes x^2 \\otimes ... \\otimes x^{k + 1} = 1 \\otimes x \\otimes x^2\n  \\otimes ... \\otimes x^k; e.g., TropicalWeight).\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    nstate: State number threshold (ignored if `reverse` is True).\n    queue_type: A string matching a known queue type; one of: \"auto\", \"fifo\",\n        \"lifo\", \"shortest\", \"state\", \"top\" (ignored if `reverse` is True).\n    reverse: Should the reverse distance (from each state to the final state)\n        be computed?\n\n  Returns:\n    A list of Weight objects representing the shortest distance for each state.\n  ";
+static PyMethodDef __pyx_mdef_9pywrapfst_53shortestdistance = {"shortestdistance", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_53shortestdistance, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_52shortestdistance};
+static PyObject *__pyx_pw_9pywrapfst_53shortestdistance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   float __pyx_v_delta;
   __pyx_t_10basictypes_int64 __pyx_v_nstate;
@@ -41375,7 +40432,7 @@ static PyObject *__pyx_pw_9pywrapfst_51shortestdistance(PyObject *__pyx_self, Py
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "shortestdistance") < 0)) __PYX_ERR(0, 3949, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "shortestdistance") < 0)) __PYX_ERR(0, 3967, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -41394,21 +40451,21 @@ static PyObject *__pyx_pw_9pywrapfst_51shortestdistance(PyObject *__pyx_self, Py
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3950, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3968, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__84;
+      __pyx_v_delta = __pyx_k__48;
     }
     if (values[2]) {
-      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[2]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3951, __pyx_L3_error)
+      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[2]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3969, __pyx_L3_error)
     } else {
-      __pyx_v_nstate = __pyx_k__85;
+      __pyx_v_nstate = __pyx_k__49;
     }
     __pyx_v_queue_type = values[3];
     if (values[4]) {
-      __pyx_v_reverse = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_reverse == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3953, __pyx_L3_error)
+      __pyx_v_reverse = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_reverse == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3971, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3953
+      /* "pywrapfst.pyx":3971
  *                      int64 nstate=fst.kNoStateId,
  *                      queue_type=b"auto",
  *                      bool reverse=False):             # <<<<<<<<<<<<<<
@@ -41420,16 +40477,16 @@ static PyObject *__pyx_pw_9pywrapfst_51shortestdistance(PyObject *__pyx_self, Py
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("shortestdistance", 0, 1, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3949, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("shortestdistance", 0, 1, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3967, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.shortestdistance", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3949, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_50shortestdistance(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_nstate, __pyx_v_queue_type, __pyx_v_reverse);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3967, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_52shortestdistance(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_nstate, __pyx_v_queue_type, __pyx_v_reverse);
 
-  /* "pywrapfst.pyx":3949
+  /* "pywrapfst.pyx":3967
  * 
  * 
  * def shortestdistance(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -41446,10 +40503,10 @@ static PyObject *__pyx_pw_9pywrapfst_51shortestdistance(PyObject *__pyx_self, Py
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_50shortestdistance(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_queue_type, bool __pyx_v_reverse) {
+static PyObject *__pyx_pf_9pywrapfst_52shortestdistance(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_queue_type, bool __pyx_v_reverse) {
   std::unique_ptr<std::vector<fst::script::WeightClass> >  __pyx_v_distance;
   std::string __pyx_v_weight_type;
-  fst::script::WeightClass __pyx_v_weight;
+  fst::script::WeightClass __pyx_7genexpr__pyx_v_weight;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   std::vector<fst::script::WeightClass>  *__pyx_t_1;
@@ -41462,7 +40519,7 @@ static PyObject *__pyx_pf_9pywrapfst_50shortestdistance(CYTHON_UNUSED PyObject *
   PyObject *__pyx_t_8 = NULL;
   __Pyx_RefNannySetupContext("shortestdistance", 0);
 
-  /* "pywrapfst.pyx":3981
+  /* "pywrapfst.pyx":3999
  *   """
  *   cdef unique_ptr[vector[fst.WeightClass]] distance
  *   distance.reset(_shortestdistance(ifst, delta, nstate, queue_type, reverse))             # <<<<<<<<<<<<<<
@@ -41474,10 +40531,10 @@ static PyObject *__pyx_pf_9pywrapfst_50shortestdistance(CYTHON_UNUSED PyObject *
   __pyx_t_2.nstate = __pyx_v_nstate;
   __pyx_t_2.queue_type = __pyx_v_queue_type;
   __pyx_t_2.reverse = __pyx_v_reverse;
-  __pyx_t_1 = __pyx_f_9pywrapfst__shortestdistance(__pyx_v_ifst, &__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3981, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst__shortestdistance(__pyx_v_ifst, &__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 3999, __pyx_L1_error)
   __pyx_v_distance.reset(__pyx_t_1);
 
-  /* "pywrapfst.pyx":3982
+  /* "pywrapfst.pyx":4000
  *   cdef unique_ptr[vector[fst.WeightClass]] distance
  *   distance.reset(_shortestdistance(ifst, delta, nstate, queue_type, reverse))
  *   cdef string weight_type = ifst.weight_type()             # <<<<<<<<<<<<<<
@@ -41486,11 +40543,11 @@ static PyObject *__pyx_pf_9pywrapfst_50shortestdistance(CYTHON_UNUSED PyObject *
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-    __PYX_ERR(0, 3982, __pyx_L1_error)
+    __PYX_ERR(0, 4000, __pyx_L1_error)
   }
   __pyx_v_weight_type = ((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0);
 
-  /* "pywrapfst.pyx":3983
+  /* "pywrapfst.pyx":4001
  *   distance.reset(_shortestdistance(ifst, delta, nstate, queue_type, reverse))
  *   cdef string weight_type = ifst.weight_type()
  *   return [Weight(weight_type, weight.ToString()) for weight in deref(distance)]             # <<<<<<<<<<<<<<
@@ -41498,38 +40555,40 @@ static PyObject *__pyx_pf_9pywrapfst_50shortestdistance(CYTHON_UNUSED PyObject *
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3983, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_1 = &(*__pyx_v_distance);
-  __pyx_t_4 = __pyx_t_1->begin();
-  for (;;) {
-    if (!(__pyx_t_4 != __pyx_t_1->end())) break;
-    __pyx_t_5 = *__pyx_t_4;
-    ++__pyx_t_4;
-    __pyx_v_weight = __pyx_t_5;
-    __pyx_t_6 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_weight_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3983, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_7 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_weight.ToString()); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3983, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3983, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __Pyx_GIVEREF(__pyx_t_6);
-    PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6);
-    __Pyx_GIVEREF(__pyx_t_7);
-    PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_7);
-    __pyx_t_6 = 0;
-    __pyx_t_7 = 0;
-    __pyx_t_7 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_t_8, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3983, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-    if (unlikely(__Pyx_ListComp_Append(__pyx_t_3, (PyObject*)__pyx_t_7))) __PYX_ERR(0, 3983, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  }
+  { /* enter inner scope */
+    __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4001, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = &(*__pyx_v_distance);
+    __pyx_t_4 = __pyx_t_1->begin();
+    for (;;) {
+      if (!(__pyx_t_4 != __pyx_t_1->end())) break;
+      __pyx_t_5 = *__pyx_t_4;
+      ++__pyx_t_4;
+      __pyx_7genexpr__pyx_v_weight = __pyx_t_5;
+      __pyx_t_6 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_weight_type); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4001, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_6);
+      __pyx_t_7 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_7genexpr__pyx_v_weight.ToString()); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4001, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 4001, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_8);
+      __Pyx_GIVEREF(__pyx_t_6);
+      PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6);
+      __Pyx_GIVEREF(__pyx_t_7);
+      PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_7);
+      __pyx_t_6 = 0;
+      __pyx_t_7 = 0;
+      __pyx_t_7 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_9pywrapfst_Weight), __pyx_t_8, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4001, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      if (unlikely(__Pyx_ListComp_Append(__pyx_t_3, (PyObject*)__pyx_t_7))) __PYX_ERR(0, 4001, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    }
+  } /* exit inner scope */
   __pyx_r = __pyx_t_3;
   __pyx_t_3 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3949
+  /* "pywrapfst.pyx":3967
  * 
  * 
  * def shortestdistance(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -41551,7 +40610,7 @@ static PyObject *__pyx_pf_9pywrapfst_50shortestdistance(CYTHON_UNUSED PyObject *
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":3986
+/* "pywrapfst.pyx":4004
  * 
  * 
  * cpdef _MutableFst shortestpath(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -41559,14 +40618,14 @@ static PyObject *__pyx_pf_9pywrapfst_50shortestdistance(CYTHON_UNUSED PyObject *
  *                                int32 nshortest=1,
  */
 
-static PyObject *__pyx_pw_9pywrapfst_53shortestpath(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_55shortestpath(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_shortestpath(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_shortestpath *__pyx_optional_args) {
-  float __pyx_v_delta = __pyx_k__86;
+  float __pyx_v_delta = __pyx_k__50;
   __pyx_t_10basictypes_int32 __pyx_v_nshortest = ((__pyx_t_10basictypes_int32)1);
-  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__87;
+  __pyx_t_10basictypes_int64 __pyx_v_nstate = __pyx_k__51;
   PyObject *__pyx_v_queue_type = ((PyObject *)__pyx_n_b_auto);
 
-  /* "pywrapfst.pyx":3991
+  /* "pywrapfst.pyx":4009
  *                                int64 nstate=fst.kNoStateId,
  *                                queue_type=b"auto",
  *                                bool unique=False,             # <<<<<<<<<<<<<<
@@ -41575,7 +40634,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_shortestpath(
  */
   bool __pyx_v_unique = ((bool)0);
 
-  /* "pywrapfst.pyx":3992
+  /* "pywrapfst.pyx":4010
  *                                queue_type=b"auto",
  *                                bool unique=False,
  *                                weight=None):             # <<<<<<<<<<<<<<
@@ -41614,7 +40673,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_shortestpath(
     }
   }
 
-  /* "pywrapfst.pyx":4024
+  /* "pywrapfst.pyx":4042
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -41623,11 +40682,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_shortestpath(
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 4024, __pyx_L1_error)
+    __PYX_ERR(0, 4042, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":4026
+  /* "pywrapfst.pyx":4044
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   # Threshold is set to semiring Zero (no pruning) if no weight is specified.
  *   cdef fst.WeightClass wc = _get_WeightClass_or_Zero(ifst.weight_type(), weight)             # <<<<<<<<<<<<<<
@@ -41636,22 +40695,22 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_shortestpath(
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "weight_type");
-    __PYX_ERR(0, 4026, __pyx_L1_error)
+    __PYX_ERR(0, 4044, __pyx_L1_error)
   }
-  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4026, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst__get_WeightClass_or_Zero(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->weight_type(__pyx_v_ifst, 0), __pyx_v_weight); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4044, __pyx_L1_error)
   __pyx_v_wc = __pyx_t_1;
 
-  /* "pywrapfst.pyx":4028
+  /* "pywrapfst.pyx":4046
  *   cdef fst.WeightClass wc = _get_WeightClass_or_Zero(ifst.weight_type(), weight)
  *   cdef unique_ptr[fst.ShortestPathOptions] opts
  *   opts.reset(new fst.ShortestPathOptions(_get_queue_type(tostring(queue_type)),             # <<<<<<<<<<<<<<
  *                                          nshortest, unique, delta, wc, nstate))
  *   fst.ShortestPath(deref(ifst._fst), tfst.get(), deref(opts))
  */
-  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_queue_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4028, __pyx_L1_error)
-  __pyx_t_3 = __pyx_f_9pywrapfst__get_queue_type(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4028, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_queue_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4046, __pyx_L1_error)
+  __pyx_t_3 = __pyx_f_9pywrapfst__get_queue_type(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4046, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":4029
+  /* "pywrapfst.pyx":4047
  *   cdef unique_ptr[fst.ShortestPathOptions] opts
  *   opts.reset(new fst.ShortestPathOptions(_get_queue_type(tostring(queue_type)),
  *                                          nshortest, unique, delta, wc, nstate))             # <<<<<<<<<<<<<<
@@ -41660,7 +40719,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_shortestpath(
  */
   __pyx_v_opts.reset(new fst::script::ShortestPathOptions(__pyx_t_3, __pyx_v_nshortest, __pyx_v_unique, __pyx_v_delta, __pyx_v_wc, __pyx_v_nstate));
 
-  /* "pywrapfst.pyx":4030
+  /* "pywrapfst.pyx":4048
  *   opts.reset(new fst.ShortestPathOptions(_get_queue_type(tostring(queue_type)),
  *                                          nshortest, unique, delta, wc, nstate))
  *   fst.ShortestPath(deref(ifst._fst), tfst.get(), deref(opts))             # <<<<<<<<<<<<<<
@@ -41669,11 +40728,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_shortestpath(
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 4030, __pyx_L1_error)
+    __PYX_ERR(0, 4048, __pyx_L1_error)
   }
   fst::script::ShortestPath((*__pyx_v_ifst->_fst), __pyx_v_tfst.get(), (*__pyx_v_opts));
 
-  /* "pywrapfst.pyx":4031
+  /* "pywrapfst.pyx":4049
  *                                          nshortest, unique, delta, wc, nstate))
  *   fst.ShortestPath(deref(ifst._fst), tfst.get(), deref(opts))
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -41681,13 +40740,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_shortestpath(
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_4 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4031, __pyx_L1_error)
+  __pyx_t_4 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4049, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_4);
   __pyx_t_4 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":3986
+  /* "pywrapfst.pyx":4004
  * 
  * 
  * cpdef _MutableFst shortestpath(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -41707,9 +40766,9 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_shortestpath(
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_53shortestpath(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_52shortestpath[] = "\n  shortestpath(ifst, delta=1e-6, nshortest=1, nstate=NO_STATE_ID,\n               queue_type=\"auto\", unique=False, weight=None)\n\n  Construct an FST containing the shortest path(s) in the input FST.\n\n  This operation produces an FST containing the n-shortest paths in the input\n  FST. The n-shortest paths are the n-lowest weight paths w.r.t. the natural\n  semiring order. The single path that can be read from the ith of at most n\n  transitions leaving the initial state of the resulting FST is the ith\n  shortest path. The weights need to be right distributive and have the path\n  property. They also need to be left distributive as well for n-shortest with\n  n > 1 (e.g., TropicalWeight).\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    nshortest: The number of paths to return.\n    nstate: State number threshold.\n    queue_type: A string matching a known queue type; one of: \"auto\", \"fifo\",\n        \"lifo\", \"shortest\", \"state\", \"top\".\n    unique: Should the resulting FST only contain distinct paths? (Requires\n        the input FST to be an acceptor; epsilons are treated as if they are\n        regular symbols.)\n    weight: A Weight or weight string indicating the desired weight threshold\n        below which paths are pruned; if omitted, no paths are pruned.\n\n  Returns:\n    An FST containing the n-shortest paths.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_53shortestpath(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_55shortestpath(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_54shortestpath[] = "\n  shortestpath(ifst, delta=1e-6, nshortest=1, nstate=NO_STATE_ID,\n               queue_type=\"auto\", unique=False, weight=None)\n\n  Construct an FST containing the shortest path(s) in the input FST.\n\n  This operation produces an FST containing the n-shortest paths in the input\n  FST. The n-shortest paths are the n-lowest weight paths w.r.t. the natural\n  semiring order. The single path that can be read from the ith of at most n\n  transitions leaving the initial state of the resulting FST is the ith\n  shortest path. The weights need to be right distributive and have the path\n  property. They also need to be left distributive as well for n-shortest with\n  n > 1 (e.g., TropicalWeight).\n\n  Args:\n    ifst: The input FST.\n    delta: Comparison/quantization delta.\n    nshortest: The number of paths to return.\n    nstate: State number threshold.\n    queue_type: A string matching a known queue type; one of: \"auto\", \"fifo\",\n        \"lifo\", \"shortest\", \"state\", \"top\".\n    unique: Should the resulting FST only contain distinct paths? (Requires\n        the input FST to be an acceptor; epsilons are treated as if they are\n        regular symbols.)\n    weight: A Weight or weight string indicating the desired weight threshold\n        below which paths are pruned; if omitted, no paths are pruned.\n\n  Returns:\n    An FST containing the n-shortest paths.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_55shortestpath(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   float __pyx_v_delta;
   __pyx_t_10basictypes_int32 __pyx_v_nshortest;
@@ -41725,7 +40784,7 @@ static PyObject *__pyx_pw_9pywrapfst_53shortestpath(PyObject *__pyx_self, PyObje
     PyObject* values[7] = {0,0,0,0,0,0,0};
     values[4] = ((PyObject *)__pyx_n_b_auto);
 
-    /* "pywrapfst.pyx":3992
+    /* "pywrapfst.pyx":4010
  *                                queue_type=b"auto",
  *                                bool unique=False,
  *                                weight=None):             # <<<<<<<<<<<<<<
@@ -41797,7 +40856,7 @@ static PyObject *__pyx_pw_9pywrapfst_53shortestpath(PyObject *__pyx_self, PyObje
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "shortestpath") < 0)) __PYX_ERR(0, 3986, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "shortestpath") < 0)) __PYX_ERR(0, 4004, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -41820,26 +40879,26 @@ static PyObject *__pyx_pw_9pywrapfst_53shortestpath(PyObject *__pyx_self, PyObje
     }
     __pyx_v_ifst = ((struct __pyx_obj_9pywrapfst__Fst *)values[0]);
     if (values[1]) {
-      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 3987, __pyx_L3_error)
+      __pyx_v_delta = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_delta == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 4005, __pyx_L3_error)
     } else {
-      __pyx_v_delta = __pyx_k__86;
+      __pyx_v_delta = __pyx_k__50;
     }
     if (values[2]) {
-      __pyx_v_nshortest = __Pyx_PyInt_As_int32_t(values[2]); if (unlikely((__pyx_v_nshortest == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3988, __pyx_L3_error)
+      __pyx_v_nshortest = __Pyx_PyInt_As_int32_t(values[2]); if (unlikely((__pyx_v_nshortest == ((int32_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4006, __pyx_L3_error)
     } else {
       __pyx_v_nshortest = ((__pyx_t_10basictypes_int32)1);
     }
     if (values[3]) {
-      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3989, __pyx_L3_error)
+      __pyx_v_nstate = __Pyx_PyInt_As_int64_t(values[3]); if (unlikely((__pyx_v_nstate == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4007, __pyx_L3_error)
     } else {
-      __pyx_v_nstate = __pyx_k__87;
+      __pyx_v_nstate = __pyx_k__51;
     }
     __pyx_v_queue_type = values[4];
     if (values[5]) {
-      __pyx_v_unique = __Pyx_PyObject_IsTrue(values[5]); if (unlikely((__pyx_v_unique == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 3991, __pyx_L3_error)
+      __pyx_v_unique = __Pyx_PyObject_IsTrue(values[5]); if (unlikely((__pyx_v_unique == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4009, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":3991
+      /* "pywrapfst.pyx":4009
  *                                int64 nstate=fst.kNoStateId,
  *                                queue_type=b"auto",
  *                                bool unique=False,             # <<<<<<<<<<<<<<
@@ -41852,16 +40911,16 @@ static PyObject *__pyx_pw_9pywrapfst_53shortestpath(PyObject *__pyx_self, PyObje
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("shortestpath", 0, 1, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 3986, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("shortestpath", 0, 1, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4004, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.shortestpath", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 3986, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_52shortestpath(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_nshortest, __pyx_v_nstate, __pyx_v_queue_type, __pyx_v_unique, __pyx_v_weight);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 4004, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_54shortestpath(__pyx_self, __pyx_v_ifst, __pyx_v_delta, __pyx_v_nshortest, __pyx_v_nstate, __pyx_v_queue_type, __pyx_v_unique, __pyx_v_weight);
 
-  /* "pywrapfst.pyx":3986
+  /* "pywrapfst.pyx":4004
  * 
  * 
  * cpdef _MutableFst shortestpath(_Fst ifst,             # <<<<<<<<<<<<<<
@@ -41878,7 +40937,7 @@ static PyObject *__pyx_pw_9pywrapfst_53shortestpath(PyObject *__pyx_self, PyObje
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_52shortestpath(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int32 __pyx_v_nshortest, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_queue_type, bool __pyx_v_unique, PyObject *__pyx_v_weight) {
+static PyObject *__pyx_pf_9pywrapfst_54shortestpath(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, float __pyx_v_delta, __pyx_t_10basictypes_int32 __pyx_v_nshortest, __pyx_t_10basictypes_int64 __pyx_v_nstate, PyObject *__pyx_v_queue_type, bool __pyx_v_unique, PyObject *__pyx_v_weight) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -41892,7 +40951,7 @@ static PyObject *__pyx_pf_9pywrapfst_52shortestpath(CYTHON_UNUSED PyObject *__py
   __pyx_t_2.queue_type = __pyx_v_queue_type;
   __pyx_t_2.unique = __pyx_v_unique;
   __pyx_t_2.weight = __pyx_v_weight;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_shortestpath(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3986, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_shortestpath(__pyx_v_ifst, 0, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4004, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -41909,7 +40968,7 @@ static PyObject *__pyx_pf_9pywrapfst_52shortestpath(CYTHON_UNUSED PyObject *__py
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4034
+/* "pywrapfst.pyx":4052
  * 
  * 
  * cpdef _Fst statemap(_Fst ifst, map_type):             # <<<<<<<<<<<<<<
@@ -41917,7 +40976,7 @@ static PyObject *__pyx_pf_9pywrapfst_52shortestpath(CYTHON_UNUSED PyObject *__py
  *   state_map(ifst, map_type)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_55statemap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_57statemap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_statemap(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, PyObject *__pyx_v_map_type, CYTHON_UNUSED int __pyx_skip_dispatch) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -41925,7 +40984,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_statemap(struct __py
   struct __pyx_opt_args_9pywrapfst__map __pyx_t_2;
   __Pyx_RefNannySetupContext("statemap", 0);
 
-  /* "pywrapfst.pyx":4057
+  /* "pywrapfst.pyx":4075
  *   See also: `arcmap`.
  *   """
  *   return _map(ifst, fst.kDelta, map_type, 1., None)             # <<<<<<<<<<<<<<
@@ -41938,13 +40997,13 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_statemap(struct __py
   __pyx_t_2.map_type = __pyx_v_map_type;
   __pyx_t_2.power = 1.;
   __pyx_t_2.weight = Py_None;
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__map(__pyx_v_ifst, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4057, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__map(__pyx_v_ifst, &__pyx_t_2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4075, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4034
+  /* "pywrapfst.pyx":4052
  * 
  * 
  * cpdef _Fst statemap(_Fst ifst, map_type):             # <<<<<<<<<<<<<<
@@ -41964,9 +41023,9 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_statemap(struct __py
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_55statemap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9pywrapfst_54statemap[] = "\n  state_map(ifst, map_type)\n\n  Constructively applies a transform to all states.\n\n  This operation transforms each state according to the requested map type.\n  Note that currently, only one state-mapping operation is supported.\n\n  Args:\n    ifst: The input FST.\n    map_type: A string matching a known mapping operation; one of: \"arc_sum\"\n        (sum weights of identically-labeled multi-arcs), \"arc_unique\" (deletes\n        non-unique identically-labeled multi-arcs).\n\n  Returns:\n    An FST with states remapped.\n\n  Raises:\n    FstArgError: Unknown map type.\n\n  See also: `arcmap`.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_55statemap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9pywrapfst_57statemap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9pywrapfst_56statemap[] = "\n  state_map(ifst, map_type)\n\n  Constructively applies a transform to all states.\n\n  This operation transforms each state according to the requested map type.\n  Note that currently, only one state-mapping operation is supported.\n\n  Args:\n    ifst: The input FST.\n    map_type: A string matching a known mapping operation; one of: \"arc_sum\"\n        (sum weights of identically-labeled multi-arcs), \"arc_unique\" (deletes\n        non-unique identically-labeled multi-arcs).\n\n  Returns:\n    An FST with states remapped.\n\n  Raises:\n    FstArgError: Unknown map type.\n\n  See also: `arcmap`.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_57statemap(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst = 0;
   PyObject *__pyx_v_map_type = 0;
   PyObject *__pyx_r = 0;
@@ -41995,11 +41054,11 @@ static PyObject *__pyx_pw_9pywrapfst_55statemap(PyObject *__pyx_self, PyObject *
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_map_type)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("statemap", 1, 2, 2, 1); __PYX_ERR(0, 4034, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("statemap", 1, 2, 2, 1); __PYX_ERR(0, 4052, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "statemap") < 0)) __PYX_ERR(0, 4034, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "statemap") < 0)) __PYX_ERR(0, 4052, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -42012,14 +41071,14 @@ static PyObject *__pyx_pw_9pywrapfst_55statemap(PyObject *__pyx_self, PyObject *
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("statemap", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4034, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("statemap", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4052, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.statemap", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 4034, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_54statemap(__pyx_self, __pyx_v_ifst, __pyx_v_map_type);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 4052, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_56statemap(__pyx_self, __pyx_v_ifst, __pyx_v_map_type);
 
   /* function exit code */
   goto __pyx_L0;
@@ -42030,13 +41089,13 @@ static PyObject *__pyx_pw_9pywrapfst_55statemap(PyObject *__pyx_self, PyObject *
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_54statemap(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, PyObject *__pyx_v_map_type) {
+static PyObject *__pyx_pf_9pywrapfst_56statemap(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, PyObject *__pyx_v_map_type) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("statemap", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_statemap(__pyx_v_ifst, __pyx_v_map_type, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4034, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_statemap(__pyx_v_ifst, __pyx_v_map_type, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4052, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -42053,7 +41112,7 @@ static PyObject *__pyx_pf_9pywrapfst_54statemap(CYTHON_UNUSED PyObject *__pyx_se
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4060
+/* "pywrapfst.pyx":4078
  * 
  * 
  * cpdef _MutableFst synchronize(_Fst ifst):             # <<<<<<<<<<<<<<
@@ -42061,7 +41120,7 @@ static PyObject *__pyx_pf_9pywrapfst_54statemap(CYTHON_UNUSED PyObject *__pyx_se
  *   synchronize(ifst)
  */
 
-static PyObject *__pyx_pw_9pywrapfst_57synchronize(PyObject *__pyx_self, PyObject *__pyx_v_ifst); /*proto*/
+static PyObject *__pyx_pw_9pywrapfst_59synchronize(PyObject *__pyx_self, PyObject *__pyx_v_ifst); /*proto*/
 static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_synchronize(struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst, CYTHON_UNUSED int __pyx_skip_dispatch) {
   std::unique_ptr<fst::script::VectorFstClass>  __pyx_v_tfst;
   struct __pyx_obj_9pywrapfst__MutableFst *__pyx_r = NULL;
@@ -42069,7 +41128,7 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_synchronize(s
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("synchronize", 0);
 
-  /* "pywrapfst.pyx":4080
+  /* "pywrapfst.pyx":4098
  *   """
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))             # <<<<<<<<<<<<<<
@@ -42078,11 +41137,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_synchronize(s
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "arc_type");
-    __PYX_ERR(0, 4080, __pyx_L1_error)
+    __PYX_ERR(0, 4098, __pyx_L1_error)
   }
   __pyx_v_tfst.reset(new fst::script::VectorFstClass(((struct __pyx_vtabstruct_9pywrapfst__Fst *)__pyx_v_ifst->__pyx_vtab)->arc_type(__pyx_v_ifst, 0)));
 
-  /* "pywrapfst.pyx":4081
+  /* "pywrapfst.pyx":4099
  *   cdef unique_ptr[fst.VectorFstClass] tfst
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   fst.Synchronize(deref(ifst._fst), tfst.get())             # <<<<<<<<<<<<<<
@@ -42091,11 +41150,11 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_synchronize(s
  */
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 4081, __pyx_L1_error)
+    __PYX_ERR(0, 4099, __pyx_L1_error)
   }
   fst::script::Synchronize((*__pyx_v_ifst->_fst), __pyx_v_tfst.get());
 
-  /* "pywrapfst.pyx":4082
+  /* "pywrapfst.pyx":4100
  *   tfst.reset(new fst.VectorFstClass(ifst.arc_type()))
  *   fst.Synchronize(deref(ifst._fst), tfst.get())
  *   return _init_MutableFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -42103,13 +41162,13 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_synchronize(s
  * 
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4082, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_MutableFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4100, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__MutableFst *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4060
+  /* "pywrapfst.pyx":4078
  * 
  * 
  * cpdef _MutableFst synchronize(_Fst ifst):             # <<<<<<<<<<<<<<
@@ -42129,14 +41188,14 @@ static struct __pyx_obj_9pywrapfst__MutableFst *__pyx_f_9pywrapfst_synchronize(s
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_57synchronize(PyObject *__pyx_self, PyObject *__pyx_v_ifst); /*proto*/
-static char __pyx_doc_9pywrapfst_56synchronize[] = "\n  synchronize(ifst)\n\n  Constructively synchronizes an FST.\n\n  This operation synchronizes a transducer. The result will be an equivalent\n  FST that has the property that during the traversal of a path, the delay is\n  either zero or strictly increasing, where the delay is the difference between\n  the number of non-epsilon output labels and input labels along the path. For\n  the algorithm to terminate, the input transducer must have bounded delay,\n  i.e., the delay of every cycle must be zero.\n\n  Args:\n    ifst: The input FST.\n\n  Returns:\n    An equivalent synchronized FST.\n  ";
-static PyObject *__pyx_pw_9pywrapfst_57synchronize(PyObject *__pyx_self, PyObject *__pyx_v_ifst) {
+static PyObject *__pyx_pw_9pywrapfst_59synchronize(PyObject *__pyx_self, PyObject *__pyx_v_ifst); /*proto*/
+static char __pyx_doc_9pywrapfst_58synchronize[] = "\n  synchronize(ifst)\n\n  Constructively synchronizes an FST.\n\n  This operation synchronizes a transducer. The result will be an equivalent\n  FST that has the property that during the traversal of a path, the delay is\n  either zero or strictly increasing, where the delay is the difference between\n  the number of non-epsilon output labels and input labels along the path. For\n  the algorithm to terminate, the input transducer must have bounded delay,\n  i.e., the delay of every cycle must be zero.\n\n  Args:\n    ifst: The input FST.\n\n  Returns:\n    An equivalent synchronized FST.\n  ";
+static PyObject *__pyx_pw_9pywrapfst_59synchronize(PyObject *__pyx_self, PyObject *__pyx_v_ifst) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("synchronize (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 4060, __pyx_L1_error)
-  __pyx_r = __pyx_pf_9pywrapfst_56synchronize(__pyx_self, ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_ifst));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 4078, __pyx_L1_error)
+  __pyx_r = __pyx_pf_9pywrapfst_58synchronize(__pyx_self, ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_ifst));
 
   /* function exit code */
   goto __pyx_L0;
@@ -42147,13 +41206,13 @@ static PyObject *__pyx_pw_9pywrapfst_57synchronize(PyObject *__pyx_self, PyObjec
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9pywrapfst_56synchronize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst) {
+static PyObject *__pyx_pf_9pywrapfst_58synchronize(CYTHON_UNUSED PyObject *__pyx_self, struct __pyx_obj_9pywrapfst__Fst *__pyx_v_ifst) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("synchronize", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_synchronize(__pyx_v_ifst, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4060, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_synchronize(__pyx_v_ifst, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4078, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -42170,7 +41229,7 @@ static PyObject *__pyx_pf_9pywrapfst_56synchronize(CYTHON_UNUSED PyObject *__pyx
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4139
+/* "pywrapfst.pyx":4157
  *   """
  * 
  *   def __cinit__(self,             # <<<<<<<<<<<<<<
@@ -42198,7 +41257,7 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_fst_type,&__pyx_n_s_arc_type,&__pyx_n_s_isymbols,&__pyx_n_s_osymbols,&__pyx_n_s_ssymbols,&__pyx_n_s_acceptor,&__pyx_n_s_keep_isymbols,&__pyx_n_s_keep_osymbols,&__pyx_n_s_keep_state_numbering,&__pyx_n_s_allow_negative_labels,0};
     PyObject* values[10] = {0,0,0,0,0,0,0,0,0,0};
 
-    /* "pywrapfst.pyx":4142
+    /* "pywrapfst.pyx":4160
  *                 string fst_type=b"vector",
  *                 string arc_type=b"standard",
  *                 SymbolTable isymbols=None,             # <<<<<<<<<<<<<<
@@ -42207,7 +41266,7 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
  */
     values[2] = (PyObject *)((struct __pyx_obj_9pywrapfst_SymbolTable *)Py_None);
 
-    /* "pywrapfst.pyx":4143
+    /* "pywrapfst.pyx":4161
  *                 string arc_type=b"standard",
  *                 SymbolTable isymbols=None,
  *                 SymbolTable osymbols=None,             # <<<<<<<<<<<<<<
@@ -42216,7 +41275,7 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
  */
     values[3] = (PyObject *)((struct __pyx_obj_9pywrapfst_SymbolTable *)Py_None);
 
-    /* "pywrapfst.pyx":4144
+    /* "pywrapfst.pyx":4162
  *                 SymbolTable isymbols=None,
  *                 SymbolTable osymbols=None,
  *                 SymbolTable ssymbols=None,             # <<<<<<<<<<<<<<
@@ -42314,7 +41373,7 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) __PYX_ERR(0, 4139, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) __PYX_ERR(0, 4157, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -42343,23 +41402,23 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
       }
     }
     if (values[0]) {
-      __pyx_v_fst_type = __pyx_convert_string_from_py_std__in_string(values[0]); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4140, __pyx_L3_error)
+      __pyx_v_fst_type = __pyx_convert_string_from_py_std__in_string(values[0]); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4158, __pyx_L3_error)
     } else {
-      __pyx_v_fst_type = __pyx_k__88;
+      __pyx_v_fst_type = __pyx_k__52;
     }
     if (values[1]) {
-      __pyx_v_arc_type = __pyx_convert_string_from_py_std__in_string(values[1]); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4141, __pyx_L3_error)
+      __pyx_v_arc_type = __pyx_convert_string_from_py_std__in_string(values[1]); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4159, __pyx_L3_error)
     } else {
-      __pyx_v_arc_type = __pyx_k__89;
+      __pyx_v_arc_type = __pyx_k__53;
     }
     __pyx_v_isymbols = ((struct __pyx_obj_9pywrapfst_SymbolTable *)values[2]);
     __pyx_v_osymbols = ((struct __pyx_obj_9pywrapfst_SymbolTable *)values[3]);
     __pyx_v_ssymbols = ((struct __pyx_obj_9pywrapfst_SymbolTable *)values[4]);
     if (values[5]) {
-      __pyx_v_acceptor = __Pyx_PyObject_IsTrue(values[5]); if (unlikely((__pyx_v_acceptor == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4145, __pyx_L3_error)
+      __pyx_v_acceptor = __Pyx_PyObject_IsTrue(values[5]); if (unlikely((__pyx_v_acceptor == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4163, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":4145
+      /* "pywrapfst.pyx":4163
  *                 SymbolTable osymbols=None,
  *                 SymbolTable ssymbols=None,
  *                 bool acceptor=False,             # <<<<<<<<<<<<<<
@@ -42369,10 +41428,10 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
       __pyx_v_acceptor = ((bool)0);
     }
     if (values[6]) {
-      __pyx_v_keep_isymbols = __Pyx_PyObject_IsTrue(values[6]); if (unlikely((__pyx_v_keep_isymbols == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4146, __pyx_L3_error)
+      __pyx_v_keep_isymbols = __Pyx_PyObject_IsTrue(values[6]); if (unlikely((__pyx_v_keep_isymbols == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4164, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":4146
+      /* "pywrapfst.pyx":4164
  *                 SymbolTable ssymbols=None,
  *                 bool acceptor=False,
  *                 bool keep_isymbols=False,             # <<<<<<<<<<<<<<
@@ -42382,10 +41441,10 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
       __pyx_v_keep_isymbols = ((bool)0);
     }
     if (values[7]) {
-      __pyx_v_keep_osymbols = __Pyx_PyObject_IsTrue(values[7]); if (unlikely((__pyx_v_keep_osymbols == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4147, __pyx_L3_error)
+      __pyx_v_keep_osymbols = __Pyx_PyObject_IsTrue(values[7]); if (unlikely((__pyx_v_keep_osymbols == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4165, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":4147
+      /* "pywrapfst.pyx":4165
  *                 bool acceptor=False,
  *                 bool keep_isymbols=False,
  *                 bool keep_osymbols=False,             # <<<<<<<<<<<<<<
@@ -42395,10 +41454,10 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
       __pyx_v_keep_osymbols = ((bool)0);
     }
     if (values[8]) {
-      __pyx_v_keep_state_numbering = __Pyx_PyObject_IsTrue(values[8]); if (unlikely((__pyx_v_keep_state_numbering == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4148, __pyx_L3_error)
+      __pyx_v_keep_state_numbering = __Pyx_PyObject_IsTrue(values[8]); if (unlikely((__pyx_v_keep_state_numbering == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4166, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":4148
+      /* "pywrapfst.pyx":4166
  *                 bool keep_isymbols=False,
  *                 bool keep_osymbols=False,
  *                 bool keep_state_numbering=False,             # <<<<<<<<<<<<<<
@@ -42408,10 +41467,10 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
       __pyx_v_keep_state_numbering = ((bool)0);
     }
     if (values[9]) {
-      __pyx_v_allow_negative_labels = __Pyx_PyObject_IsTrue(values[9]); if (unlikely((__pyx_v_allow_negative_labels == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4149, __pyx_L3_error)
+      __pyx_v_allow_negative_labels = __Pyx_PyObject_IsTrue(values[9]); if (unlikely((__pyx_v_allow_negative_labels == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4167, __pyx_L3_error)
     } else {
 
-      /* "pywrapfst.pyx":4149
+      /* "pywrapfst.pyx":4167
  *                 bool keep_osymbols=False,
  *                 bool keep_state_numbering=False,
  *                 bool allow_negative_labels=False):             # <<<<<<<<<<<<<<
@@ -42423,18 +41482,18 @@ static int __pyx_pw_9pywrapfst_8Compiler_1__cinit__(PyObject *__pyx_v_self, PyOb
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 10, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4139, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 10, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4157, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.Compiler.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_isymbols), __pyx_ptype_9pywrapfst_SymbolTable, 1, "isymbols", 0))) __PYX_ERR(0, 4142, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_osymbols), __pyx_ptype_9pywrapfst_SymbolTable, 1, "osymbols", 0))) __PYX_ERR(0, 4143, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ssymbols), __pyx_ptype_9pywrapfst_SymbolTable, 1, "ssymbols", 0))) __PYX_ERR(0, 4144, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_isymbols), __pyx_ptype_9pywrapfst_SymbolTable, 1, "isymbols", 0))) __PYX_ERR(0, 4160, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_osymbols), __pyx_ptype_9pywrapfst_SymbolTable, 1, "osymbols", 0))) __PYX_ERR(0, 4161, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ssymbols), __pyx_ptype_9pywrapfst_SymbolTable, 1, "ssymbols", 0))) __PYX_ERR(0, 4162, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_8Compiler___cinit__(((struct __pyx_obj_9pywrapfst_Compiler *)__pyx_v_self), __pyx_v_fst_type, __pyx_v_arc_type, __pyx_v_isymbols, __pyx_v_osymbols, __pyx_v_ssymbols, __pyx_v_acceptor, __pyx_v_keep_isymbols, __pyx_v_keep_osymbols, __pyx_v_keep_state_numbering, __pyx_v_allow_negative_labels);
 
-  /* "pywrapfst.pyx":4139
+  /* "pywrapfst.pyx":4157
  *   """
  * 
  *   def __cinit__(self,             # <<<<<<<<<<<<<<
@@ -42461,7 +41520,7 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
   fst::SymbolTable *__pyx_t_5;
   __Pyx_RefNannySetupContext("__cinit__", 0);
 
-  /* "pywrapfst.pyx":4150
+  /* "pywrapfst.pyx":4168
  *                 bool keep_state_numbering=False,
  *                 bool allow_negative_labels=False):
  *     self._sstrm.reset(new stringstream())             # <<<<<<<<<<<<<<
@@ -42470,45 +41529,45 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_sstrm");
-    __PYX_ERR(0, 4150, __pyx_L1_error)
+    __PYX_ERR(0, 4168, __pyx_L1_error)
   }
   __pyx_v_self->_sstrm.reset(new std::stringstream());
 
-  /* "pywrapfst.pyx":4151
+  /* "pywrapfst.pyx":4169
  *                 bool allow_negative_labels=False):
  *     self._sstrm.reset(new stringstream())
  *     self._fst_type = tostring(fst_type)             # <<<<<<<<<<<<<<
  *     self._arc_type = tostring(arc_type)
  *     self._isymbols = NULL
  */
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_fst_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4151, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_fst_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4169, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_t_1, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4151, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_t_1, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4169, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst_type");
-    __PYX_ERR(0, 4151, __pyx_L1_error)
+    __PYX_ERR(0, 4169, __pyx_L1_error)
   }
   __pyx_v_self->_fst_type = __pyx_t_2;
 
-  /* "pywrapfst.pyx":4152
+  /* "pywrapfst.pyx":4170
  *     self._sstrm.reset(new stringstream())
  *     self._fst_type = tostring(fst_type)
  *     self._arc_type = tostring(arc_type)             # <<<<<<<<<<<<<<
  *     self._isymbols = NULL
  *     if isymbols is not None:
  */
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_v_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4152, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_v_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4170, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_t_1, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4152, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_t_1, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4170, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc_type");
-    __PYX_ERR(0, 4152, __pyx_L1_error)
+    __PYX_ERR(0, 4170, __pyx_L1_error)
   }
   __pyx_v_self->_arc_type = __pyx_t_2;
 
-  /* "pywrapfst.pyx":4153
+  /* "pywrapfst.pyx":4171
  *     self._fst_type = tostring(fst_type)
  *     self._arc_type = tostring(arc_type)
  *     self._isymbols = NULL             # <<<<<<<<<<<<<<
@@ -42517,11 +41576,11 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_isymbols");
-    __PYX_ERR(0, 4153, __pyx_L1_error)
+    __PYX_ERR(0, 4171, __pyx_L1_error)
   }
   __pyx_v_self->_isymbols = NULL;
 
-  /* "pywrapfst.pyx":4154
+  /* "pywrapfst.pyx":4172
  *     self._arc_type = tostring(arc_type)
  *     self._isymbols = NULL
  *     if isymbols is not None:             # <<<<<<<<<<<<<<
@@ -42532,7 +41591,7 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
   __pyx_t_4 = (__pyx_t_3 != 0);
   if (__pyx_t_4) {
 
-    /* "pywrapfst.pyx":4155
+    /* "pywrapfst.pyx":4173
  *     self._isymbols = NULL
  *     if isymbols is not None:
  *       self._isymbols = isymbols._table             # <<<<<<<<<<<<<<
@@ -42541,16 +41600,16 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
     if (unlikely(((PyObject *)__pyx_v_isymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 4155, __pyx_L1_error)
+      __PYX_ERR(0, 4173, __pyx_L1_error)
     }
     __pyx_t_5 = __pyx_v_isymbols->__pyx_base.__pyx_base._table;
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_isymbols");
-      __PYX_ERR(0, 4155, __pyx_L1_error)
+      __PYX_ERR(0, 4173, __pyx_L1_error)
     }
     __pyx_v_self->_isymbols = __pyx_t_5;
 
-    /* "pywrapfst.pyx":4154
+    /* "pywrapfst.pyx":4172
  *     self._arc_type = tostring(arc_type)
  *     self._isymbols = NULL
  *     if isymbols is not None:             # <<<<<<<<<<<<<<
@@ -42559,7 +41618,7 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   }
 
-  /* "pywrapfst.pyx":4156
+  /* "pywrapfst.pyx":4174
  *     if isymbols is not None:
  *       self._isymbols = isymbols._table
  *     self._osymbols = NULL             # <<<<<<<<<<<<<<
@@ -42568,11 +41627,11 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_osymbols");
-    __PYX_ERR(0, 4156, __pyx_L1_error)
+    __PYX_ERR(0, 4174, __pyx_L1_error)
   }
   __pyx_v_self->_osymbols = NULL;
 
-  /* "pywrapfst.pyx":4157
+  /* "pywrapfst.pyx":4175
  *       self._isymbols = isymbols._table
  *     self._osymbols = NULL
  *     if osymbols is not None:             # <<<<<<<<<<<<<<
@@ -42583,7 +41642,7 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
   __pyx_t_3 = (__pyx_t_4 != 0);
   if (__pyx_t_3) {
 
-    /* "pywrapfst.pyx":4158
+    /* "pywrapfst.pyx":4176
  *     self._osymbols = NULL
  *     if osymbols is not None:
  *       self._osymbols = osymbols._table             # <<<<<<<<<<<<<<
@@ -42592,16 +41651,16 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
     if (unlikely(((PyObject *)__pyx_v_osymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 4158, __pyx_L1_error)
+      __PYX_ERR(0, 4176, __pyx_L1_error)
     }
     __pyx_t_5 = __pyx_v_osymbols->__pyx_base.__pyx_base._table;
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_osymbols");
-      __PYX_ERR(0, 4158, __pyx_L1_error)
+      __PYX_ERR(0, 4176, __pyx_L1_error)
     }
     __pyx_v_self->_osymbols = __pyx_t_5;
 
-    /* "pywrapfst.pyx":4157
+    /* "pywrapfst.pyx":4175
  *       self._isymbols = isymbols._table
  *     self._osymbols = NULL
  *     if osymbols is not None:             # <<<<<<<<<<<<<<
@@ -42610,7 +41669,7 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   }
 
-  /* "pywrapfst.pyx":4159
+  /* "pywrapfst.pyx":4177
  *     if osymbols is not None:
  *       self._osymbols = osymbols._table
  *     self._ssymbols = NULL             # <<<<<<<<<<<<<<
@@ -42619,11 +41678,11 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_ssymbols");
-    __PYX_ERR(0, 4159, __pyx_L1_error)
+    __PYX_ERR(0, 4177, __pyx_L1_error)
   }
   __pyx_v_self->_ssymbols = NULL;
 
-  /* "pywrapfst.pyx":4160
+  /* "pywrapfst.pyx":4178
  *       self._osymbols = osymbols._table
  *     self._ssymbols = NULL
  *     if ssymbols is not None:             # <<<<<<<<<<<<<<
@@ -42634,7 +41693,7 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
   __pyx_t_4 = (__pyx_t_3 != 0);
   if (__pyx_t_4) {
 
-    /* "pywrapfst.pyx":4161
+    /* "pywrapfst.pyx":4179
  *     self._ssymbols = NULL
  *     if ssymbols is not None:
  *       self._ssymbols = ssymbols._table             # <<<<<<<<<<<<<<
@@ -42643,16 +41702,16 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
     if (unlikely(((PyObject *)__pyx_v_ssymbols) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_table");
-      __PYX_ERR(0, 4161, __pyx_L1_error)
+      __PYX_ERR(0, 4179, __pyx_L1_error)
     }
     __pyx_t_5 = __pyx_v_ssymbols->__pyx_base.__pyx_base._table;
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_ssymbols");
-      __PYX_ERR(0, 4161, __pyx_L1_error)
+      __PYX_ERR(0, 4179, __pyx_L1_error)
     }
     __pyx_v_self->_ssymbols = __pyx_t_5;
 
-    /* "pywrapfst.pyx":4160
+    /* "pywrapfst.pyx":4178
  *       self._osymbols = osymbols._table
  *     self._ssymbols = NULL
  *     if ssymbols is not None:             # <<<<<<<<<<<<<<
@@ -42661,7 +41720,7 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   }
 
-  /* "pywrapfst.pyx":4162
+  /* "pywrapfst.pyx":4180
  *     if ssymbols is not None:
  *       self._ssymbols = ssymbols._table
  *     self._acceptor = acceptor             # <<<<<<<<<<<<<<
@@ -42670,11 +41729,11 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_acceptor");
-    __PYX_ERR(0, 4162, __pyx_L1_error)
+    __PYX_ERR(0, 4180, __pyx_L1_error)
   }
   __pyx_v_self->_acceptor = __pyx_v_acceptor;
 
-  /* "pywrapfst.pyx":4163
+  /* "pywrapfst.pyx":4181
  *       self._ssymbols = ssymbols._table
  *     self._acceptor = acceptor
  *     self._keep_isymbols = keep_isymbols             # <<<<<<<<<<<<<<
@@ -42683,11 +41742,11 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_keep_isymbols");
-    __PYX_ERR(0, 4163, __pyx_L1_error)
+    __PYX_ERR(0, 4181, __pyx_L1_error)
   }
   __pyx_v_self->_keep_isymbols = __pyx_v_keep_isymbols;
 
-  /* "pywrapfst.pyx":4164
+  /* "pywrapfst.pyx":4182
  *     self._acceptor = acceptor
  *     self._keep_isymbols = keep_isymbols
  *     self._keep_osymbols = keep_osymbols             # <<<<<<<<<<<<<<
@@ -42696,11 +41755,11 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_keep_osymbols");
-    __PYX_ERR(0, 4164, __pyx_L1_error)
+    __PYX_ERR(0, 4182, __pyx_L1_error)
   }
   __pyx_v_self->_keep_osymbols = __pyx_v_keep_osymbols;
 
-  /* "pywrapfst.pyx":4165
+  /* "pywrapfst.pyx":4183
  *     self._keep_isymbols = keep_isymbols
  *     self._keep_osymbols = keep_osymbols
  *     self._keep_state_numbering = keep_state_numbering             # <<<<<<<<<<<<<<
@@ -42709,11 +41768,11 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_keep_state_numbering");
-    __PYX_ERR(0, 4165, __pyx_L1_error)
+    __PYX_ERR(0, 4183, __pyx_L1_error)
   }
   __pyx_v_self->_keep_state_numbering = __pyx_v_keep_state_numbering;
 
-  /* "pywrapfst.pyx":4166
+  /* "pywrapfst.pyx":4184
  *     self._keep_osymbols = keep_osymbols
  *     self._keep_state_numbering = keep_state_numbering
  *     self._allow_negative_labels = allow_negative_labels             # <<<<<<<<<<<<<<
@@ -42722,11 +41781,11 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_allow_negative_labels");
-    __PYX_ERR(0, 4166, __pyx_L1_error)
+    __PYX_ERR(0, 4184, __pyx_L1_error)
   }
   __pyx_v_self->_allow_negative_labels = __pyx_v_allow_negative_labels;
 
-  /* "pywrapfst.pyx":4139
+  /* "pywrapfst.pyx":4157
  *   """
  * 
  *   def __cinit__(self,             # <<<<<<<<<<<<<<
@@ -42746,7 +41805,7 @@ static int __pyx_pf_9pywrapfst_8Compiler___cinit__(struct __pyx_obj_9pywrapfst_C
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4168
+/* "pywrapfst.pyx":4186
  *     self._allow_negative_labels = allow_negative_labels
  * 
  *   cpdef _Fst compile(self):             # <<<<<<<<<<<<<<
@@ -42768,40 +41827,53 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_compile); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4168, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_8Compiler_3compile)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_compile); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4186, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_8Compiler_3compile)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4186, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 4186, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4168, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4168, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 4168, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4183
+  /* "pywrapfst.pyx":4201
  *     """
  *     cdef unique_ptr[fst.FstClass] tfst
  *     tfst.reset(fst.CompileFstInternal(deref(self._sstrm),             # <<<<<<<<<<<<<<
@@ -42810,10 +41882,10 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_sstrm");
-    __PYX_ERR(0, 4183, __pyx_L1_error)
+    __PYX_ERR(0, 4201, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":4184
+  /* "pywrapfst.pyx":4202
  *     cdef unique_ptr[fst.FstClass] tfst
  *     tfst.reset(fst.CompileFstInternal(deref(self._sstrm),
  *         b"<pywrapfst>", self._fst_type, self._arc_type, self._isymbols,             # <<<<<<<<<<<<<<
@@ -42822,18 +41894,18 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst_type");
-    __PYX_ERR(0, 4184, __pyx_L1_error)
+    __PYX_ERR(0, 4202, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_arc_type");
-    __PYX_ERR(0, 4184, __pyx_L1_error)
+    __PYX_ERR(0, 4202, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_isymbols");
-    __PYX_ERR(0, 4184, __pyx_L1_error)
+    __PYX_ERR(0, 4202, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":4185
+  /* "pywrapfst.pyx":4203
  *     tfst.reset(fst.CompileFstInternal(deref(self._sstrm),
  *         b"<pywrapfst>", self._fst_type, self._arc_type, self._isymbols,
  *         self._osymbols, self._ssymbols, self._acceptor, self._keep_isymbols,             # <<<<<<<<<<<<<<
@@ -42842,22 +41914,22 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_osymbols");
-    __PYX_ERR(0, 4185, __pyx_L1_error)
+    __PYX_ERR(0, 4203, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_ssymbols");
-    __PYX_ERR(0, 4185, __pyx_L1_error)
+    __PYX_ERR(0, 4203, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_acceptor");
-    __PYX_ERR(0, 4185, __pyx_L1_error)
+    __PYX_ERR(0, 4203, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_keep_isymbols");
-    __PYX_ERR(0, 4185, __pyx_L1_error)
+    __PYX_ERR(0, 4203, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":4186
+  /* "pywrapfst.pyx":4204
  *         b"<pywrapfst>", self._fst_type, self._arc_type, self._isymbols,
  *         self._osymbols, self._ssymbols, self._acceptor, self._keep_isymbols,
  *         self._keep_osymbols, self._keep_state_numbering,             # <<<<<<<<<<<<<<
@@ -42866,14 +41938,14 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_keep_osymbols");
-    __PYX_ERR(0, 4186, __pyx_L1_error)
+    __PYX_ERR(0, 4204, __pyx_L1_error)
   }
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_keep_state_numbering");
-    __PYX_ERR(0, 4186, __pyx_L1_error)
+    __PYX_ERR(0, 4204, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":4187
+  /* "pywrapfst.pyx":4205
  *         self._osymbols, self._ssymbols, self._acceptor, self._keep_isymbols,
  *         self._keep_osymbols, self._keep_state_numbering,
  *         self._allow_negative_labels))             # <<<<<<<<<<<<<<
@@ -42882,10 +41954,10 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_allow_negative_labels");
-    __PYX_ERR(0, 4187, __pyx_L1_error)
+    __PYX_ERR(0, 4205, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":4183
+  /* "pywrapfst.pyx":4201
  *     """
  *     cdef unique_ptr[fst.FstClass] tfst
  *     tfst.reset(fst.CompileFstInternal(deref(self._sstrm),             # <<<<<<<<<<<<<<
@@ -42894,7 +41966,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
  */
   __pyx_v_tfst.reset(fst::script::CompileFstInternal((*__pyx_v_self->_sstrm), __pyx_k_pywrapfst, __pyx_v_self->_fst_type, __pyx_v_self->_arc_type, __pyx_v_self->_isymbols, __pyx_v_self->_osymbols, __pyx_v_self->_ssymbols, __pyx_v_self->_acceptor, __pyx_v_self->_keep_isymbols, __pyx_v_self->_keep_osymbols, __pyx_v_self->_keep_state_numbering, __pyx_v_self->_allow_negative_labels));
 
-  /* "pywrapfst.pyx":4188
+  /* "pywrapfst.pyx":4206
  *         self._keep_osymbols, self._keep_state_numbering,
  *         self._allow_negative_labels))
  *     self._sstrm.reset(new stringstream())             # <<<<<<<<<<<<<<
@@ -42903,11 +41975,11 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_sstrm");
-    __PYX_ERR(0, 4188, __pyx_L1_error)
+    __PYX_ERR(0, 4206, __pyx_L1_error)
   }
   __pyx_v_self->_sstrm.reset(new std::stringstream());
 
-  /* "pywrapfst.pyx":4189
+  /* "pywrapfst.pyx":4207
  *         self._allow_negative_labels))
  *     self._sstrm.reset(new stringstream())
  *     if tfst.get() == NULL:             # <<<<<<<<<<<<<<
@@ -42917,23 +41989,35 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
   __pyx_t_5 = ((__pyx_v_tfst.get() == NULL) != 0);
   if (unlikely(__pyx_t_5)) {
 
-    /* "pywrapfst.pyx":4190
+    /* "pywrapfst.pyx":4208
  *     self._sstrm.reset(new stringstream())
  *     if tfst.get() == NULL:
  *       raise FstOpError("Compilation failed")             # <<<<<<<<<<<<<<
  *     return _init_XFst(tfst.release())
  * 
  */
-    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4190, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__90, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4190, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4208, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __pyx_t_3 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_3)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_kp_u_Compilation_failed) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_kp_u_Compilation_failed);
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4208, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 4190, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 4208, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":4189
+    /* "pywrapfst.pyx":4207
  *         self._allow_negative_labels))
  *     self._sstrm.reset(new stringstream())
  *     if tfst.get() == NULL:             # <<<<<<<<<<<<<<
@@ -42942,7 +42026,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
  */
   }
 
-  /* "pywrapfst.pyx":4191
+  /* "pywrapfst.pyx":4209
  *     if tfst.get() == NULL:
  *       raise FstOpError("Compilation failed")
  *     return _init_XFst(tfst.release())             # <<<<<<<<<<<<<<
@@ -42950,13 +42034,13 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_8Compiler_compile(st
  *   cpdef void write(self, expression):
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
-  __pyx_t_2 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4191, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
-  __pyx_t_2 = 0;
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(__pyx_v_tfst.release())); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4209, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_1);
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4168
+  /* "pywrapfst.pyx":4186
  *     self._allow_negative_labels = allow_negative_labels
  * 
  *   cpdef _Fst compile(self):             # <<<<<<<<<<<<<<
@@ -42998,7 +42082,7 @@ static PyObject *__pyx_pf_9pywrapfst_8Compiler_2compile(struct __pyx_obj_9pywrap
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("compile", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_8Compiler_compile(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4168, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_8Compiler_compile(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4186, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -43015,7 +42099,7 @@ static PyObject *__pyx_pf_9pywrapfst_8Compiler_2compile(struct __pyx_obj_9pywrap
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4193
+/* "pywrapfst.pyx":4211
  *     return _init_XFst(tfst.release())
  * 
  *   cpdef void write(self, expression):             # <<<<<<<<<<<<<<
@@ -43025,87 +42109,122 @@ static PyObject *__pyx_pf_9pywrapfst_8Compiler_2compile(struct __pyx_obj_9pywrap
 
 static PyObject *__pyx_pw_9pywrapfst_8Compiler_5write(PyObject *__pyx_v_self, PyObject *__pyx_v_expression); /*proto*/
 static void __pyx_f_9pywrapfst_8Compiler_write(struct __pyx_obj_9pywrapfst_Compiler *__pyx_v_self, PyObject *__pyx_v_expression, int __pyx_skip_dispatch) {
+  std::string __pyx_v_line;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  std::string __pyx_t_6;
+  std::string __pyx_t_5;
+  int __pyx_t_6;
+  int __pyx_t_7;
   __Pyx_RefNannySetupContext("write", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4193, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_8Compiler_5write)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_write); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4211, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_8Compiler_5write)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_expression); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4193, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_expression) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_expression);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4211, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_expression};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4193, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_expression};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4193, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4193, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(__pyx_v_expression);
-          __Pyx_GIVEREF(__pyx_v_expression);
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_v_expression);
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4193, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
+      }
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4209
+  /* "pywrapfst.pyx":4227
  *       expression: A string expression to add to compiler string buffer.
  *     """
- *     deref(self._sstrm) << tostring(expression)             # <<<<<<<<<<<<<<
+ *     cdef string line = tostring(expression)             # <<<<<<<<<<<<<<
+ *     if not line.empty() and line.back() != b'\n':
+ *       line.append(b'\n')
+ */
+  __pyx_t_5 = __pyx_f_9pywrapfst_tostring(__pyx_v_expression, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4227, __pyx_L1_error)
+  __pyx_v_line = __pyx_t_5;
+
+  /* "pywrapfst.pyx":4228
+ *     """
+ *     cdef string line = tostring(expression)
+ *     if not line.empty() and line.back() != b'\n':             # <<<<<<<<<<<<<<
+ *       line.append(b'\n')
+ *     deref(self._sstrm) << line
+ */
+  __pyx_t_7 = ((!(__pyx_v_line.empty() != 0)) != 0);
+  if (__pyx_t_7) {
+  } else {
+    __pyx_t_6 = __pyx_t_7;
+    goto __pyx_L4_bool_binop_done;
+  }
+  __pyx_t_7 = ((__pyx_v_line.back() != '\n') != 0);
+  __pyx_t_6 = __pyx_t_7;
+  __pyx_L4_bool_binop_done:;
+  if (__pyx_t_6) {
+
+    /* "pywrapfst.pyx":4229
+ *     cdef string line = tostring(expression)
+ *     if not line.empty() and line.back() != b'\n':
+ *       line.append(b'\n')             # <<<<<<<<<<<<<<
+ *     deref(self._sstrm) << line
+ * 
+ */
+    (void)(__pyx_v_line.append(((char const *)"\n")));
+
+    /* "pywrapfst.pyx":4228
+ *     """
+ *     cdef string line = tostring(expression)
+ *     if not line.empty() and line.back() != b'\n':             # <<<<<<<<<<<<<<
+ *       line.append(b'\n')
+ *     deref(self._sstrm) << line
+ */
+  }
+
+  /* "pywrapfst.pyx":4230
+ *     if not line.empty() and line.back() != b'\n':
+ *       line.append(b'\n')
+ *     deref(self._sstrm) << line             # <<<<<<<<<<<<<<
  * 
  * 
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_sstrm");
-    __PYX_ERR(0, 4209, __pyx_L1_error)
+    __PYX_ERR(0, 4230, __pyx_L1_error)
   }
-  __pyx_t_6 = __pyx_f_9pywrapfst_tostring(__pyx_v_expression, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4209, __pyx_L1_error)
-  (void)(((*__pyx_v_self->_sstrm) << __pyx_t_6));
+  (void)(((*__pyx_v_self->_sstrm) << __pyx_v_line));
 
-  /* "pywrapfst.pyx":4193
+  /* "pywrapfst.pyx":4211
  *     return _init_XFst(tfst.release())
  * 
  *   cpdef void write(self, expression):             # <<<<<<<<<<<<<<
@@ -43120,7 +42239,6 @@ static void __pyx_f_9pywrapfst_8Compiler_write(struct __pyx_obj_9pywrapfst_Compi
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_WriteUnraisable("pywrapfst.Compiler.write", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
@@ -43128,7 +42246,7 @@ static void __pyx_f_9pywrapfst_8Compiler_write(struct __pyx_obj_9pywrapfst_Compi
 
 /* Python wrapper */
 static PyObject *__pyx_pw_9pywrapfst_8Compiler_5write(PyObject *__pyx_v_self, PyObject *__pyx_v_expression); /*proto*/
-static char __pyx_doc_9pywrapfst_8Compiler_4write[] = "\n    write(expression)\n\n    Writes a string into the compiler string buffer.\n\n    This method adds a line to the compiler string buffer. It is normally\n    invoked using the right shift operator, like so:\n\n        compiler = fst.Compiler()\n        print >> compiler, \"0 0 49 49\"\n        print >> compiler, \"0\"\n\n    Args:\n      expression: A string expression to add to compiler string buffer.\n    ";
+static char __pyx_doc_9pywrapfst_8Compiler_4write[] = "\n    write(expression)\n\n    Writes a string into the compiler string buffer.\n\n    This method adds a line to the compiler string buffer. It is normally\n    invoked using the right shift operator, like so:\n\n        compiler = fst.Compiler()\n        compiler.write(\"0 0 49 49\")\n        compiler.write(\"0\")\n\n    Args:\n      expression: A string expression to add to compiler string buffer.\n    ";
 static PyObject *__pyx_pw_9pywrapfst_8Compiler_5write(PyObject *__pyx_v_self, PyObject *__pyx_v_expression) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
@@ -43146,7 +42264,7 @@ static PyObject *__pyx_pf_9pywrapfst_8Compiler_4write(struct __pyx_obj_9pywrapfs
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("write", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_8Compiler_write(__pyx_v_self, __pyx_v_expression, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4193, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_8Compiler_write(__pyx_v_self, __pyx_v_expression, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4211, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -43194,7 +42312,7 @@ static PyObject *__pyx_pf_9pywrapfst_8Compiler_6__reduce_cython__(CYTHON_UNUSED
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__91, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__54, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -43247,7 +42365,7 @@ static PyObject *__pyx_pf_9pywrapfst_8Compiler_8__setstate_cython__(CYTHON_UNUSE
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__92, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__55, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -43270,7 +42388,7 @@ static PyObject *__pyx_pf_9pywrapfst_8Compiler_8__setstate_cython__(CYTHON_UNUSE
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4231
+/* "pywrapfst.pyx":4252
  *   """
  * 
  *   def __init__(self):             # <<<<<<<<<<<<<<
@@ -43303,31 +42421,30 @@ static int __pyx_pf_9pywrapfst_9FarReader___init__(struct __pyx_obj_9pywrapfst_F
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
-  PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":4232
+  /* "pywrapfst.pyx":4253
  * 
  *   def __init__(self):
  *     raise FstDeletedConstructorError(             # <<<<<<<<<<<<<<
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstDeletedConstructorError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4232, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstDeletedConstructorError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4253, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
 
-  /* "pywrapfst.pyx":4233
+  /* "pywrapfst.pyx":4254
  *   def __init__(self):
  *     raise FstDeletedConstructorError(
  *         "Cannot construct {}".format(self.__class__.__name__))             # <<<<<<<<<<<<<<
  * 
  *   def __repr__(self):
  */
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Cannot_construct, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4233, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Cannot_construct, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4254, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_class); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4233, __pyx_L1_error)
+  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_class); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4254, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4233, __pyx_L1_error)
+  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4254, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __pyx_t_5 = NULL;
@@ -43340,41 +42457,11 @@ static int __pyx_pf_9pywrapfst_9FarReader___init__(struct __pyx_obj_9pywrapfst_F
       __Pyx_DECREF_SET(__pyx_t_4, function);
     }
   }
-  if (!__pyx_t_5) {
-    __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4233, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_GOTREF(__pyx_t_3);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_6};
-      __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4233, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_6};
-      __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4233, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4233, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
-      __Pyx_GIVEREF(__pyx_t_6);
-      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_t_6);
-      __pyx_t_6 = 0;
-      __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4233, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    }
-  }
+  __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4254, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
@@ -43386,47 +42473,17 @@ static int __pyx_pf_9pywrapfst_9FarReader___init__(struct __pyx_obj_9pywrapfst_F
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4232, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4232, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4232, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4232, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4232, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4253, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(0, 4232, __pyx_L1_error)
+  __PYX_ERR(0, 4253, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":4231
+  /* "pywrapfst.pyx":4252
  *   """
  * 
  *   def __init__(self):             # <<<<<<<<<<<<<<
@@ -43442,14 +42499,13 @@ static int __pyx_pf_9pywrapfst_9FarReader___init__(struct __pyx_obj_9pywrapfst_F
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_AddTraceback("pywrapfst.FarReader.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = -1;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4235
+/* "pywrapfst.pyx":4256
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -43482,7 +42538,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_2__repr__(struct __pyx_obj_9pywr
   PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":4236
+  /* "pywrapfst.pyx":4257
  * 
  *   def __repr__(self):
  *     return "<{} FarReader at 0x{:x}>".format(self.far_type(), id(self))             # <<<<<<<<<<<<<<
@@ -43490,15 +42546,15 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_2__repr__(struct __pyx_obj_9pywr
  *   @classmethod
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_FarReader_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4236, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_FarReader_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4257, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "far_type");
-    __PYX_ERR(0, 4236, __pyx_L1_error)
+    __PYX_ERR(0, 4257, __pyx_L1_error)
   }
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_FarReader *)__pyx_v_self->__pyx_vtab)->far_type(__pyx_v_self, 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4236, __pyx_L1_error)
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_FarReader *)__pyx_v_self->__pyx_vtab)->far_type(__pyx_v_self, 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4257, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4236, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4257, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_t_5 = NULL;
   __pyx_t_6 = 0;
@@ -43515,7 +42571,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_2__repr__(struct __pyx_obj_9pywr
   #if CYTHON_FAST_PYCALL
   if (PyFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4236, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4257, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -43525,7 +42581,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_2__repr__(struct __pyx_obj_9pywr
   #if CYTHON_FAST_PYCCALL
   if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4236, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4257, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -43533,7 +42589,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_2__repr__(struct __pyx_obj_9pywr
   } else
   #endif
   {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4236, __pyx_L1_error)
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4257, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_7);
     if (__pyx_t_5) {
       __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
@@ -43544,7 +42600,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_2__repr__(struct __pyx_obj_9pywr
     PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_4);
     __pyx_t_3 = 0;
     __pyx_t_4 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4236, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4257, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   }
@@ -43553,7 +42609,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_2__repr__(struct __pyx_obj_9pywr
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4235
+  /* "pywrapfst.pyx":4256
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -43577,7 +42633,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_2__repr__(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4239
+/* "pywrapfst.pyx":4260
  * 
  *   @classmethod
  *   def open(cls, *filenames):             # <<<<<<<<<<<<<<
@@ -43605,200 +42661,153 @@ static PyObject *__pyx_pw_9pywrapfst_9FarReader_5open(PyObject *__pyx_v_cls, PyO
 }
 
 static PyObject *__pyx_pf_9pywrapfst_9FarReader_4open(CYTHON_UNUSED PyTypeObject *__pyx_v_cls, PyObject *__pyx_v_filenames) {
+  std::vector<std::string>  __pyx_v_filename_strings;
+  PyObject *__pyx_v_filename = NULL;
   std::unique_ptr<fst::script::FarReaderClass>  __pyx_v_tfar;
   struct __pyx_obj_9pywrapfst_FarReader *__pyx_v_result = 0;
-  PyObject *__pyx_v_filename = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  Py_ssize_t __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  std::string __pyx_t_5;
-  std::vector<std::string>  __pyx_t_6;
-  int __pyx_t_7;
+  Py_ssize_t __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  std::string __pyx_t_4;
+  int __pyx_t_5;
+  PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
   PyObject *__pyx_t_8 = NULL;
-  PyObject *__pyx_t_9 = NULL;
-  PyObject *__pyx_t_10 = NULL;
   __Pyx_RefNannySetupContext("open", 0);
-  __Pyx_INCREF(__pyx_v_filenames);
 
-  /* "pywrapfst.pyx":4257
- *       FstIOError: Read failed.
+  /* "pywrapfst.pyx":4279
  *     """
- *     filenames = [tostring(filename) for filename in filenames]             # <<<<<<<<<<<<<<
+ *     cdef vector[string] filename_strings
+ *     for filename in filenames:             # <<<<<<<<<<<<<<
+ *       filename_strings.push_back(tostring(filename))
  *     cdef unique_ptr[fst.FarReaderClass] tfar
- *     tfar.reset(fst.FarReaderClass.Open(filenames))
  */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4257, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __pyx_v_filenames; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
+  __pyx_t_1 = __pyx_v_filenames; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
   for (;;) {
-    if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+    if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
     #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-    __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_4); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 4257, __pyx_L1_error)
+    __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_3); __pyx_t_2++; if (unlikely(0 < 0)) __PYX_ERR(0, 4279, __pyx_L1_error)
     #else
-    __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4257, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4279, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
     #endif
-    __Pyx_XDECREF_SET(__pyx_v_filename, __pyx_t_4);
-    __pyx_t_4 = 0;
-    __pyx_t_5 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4257, __pyx_L1_error)
-    __pyx_t_4 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4257, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_4))) __PYX_ERR(0, 4257, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_filename, __pyx_t_3);
+    __pyx_t_3 = 0;
+
+    /* "pywrapfst.pyx":4280
+ *     cdef vector[string] filename_strings
+ *     for filename in filenames:
+ *       filename_strings.push_back(tostring(filename))             # <<<<<<<<<<<<<<
+ *     cdef unique_ptr[fst.FarReaderClass] tfar
+ *     tfar.reset(fst.FarReaderClass.Open(filename_strings))
+ */
+    __pyx_t_4 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4280, __pyx_L1_error)
+    try {
+      __pyx_v_filename_strings.push_back(__pyx_t_4);
+    } catch(...) {
+      __Pyx_CppExn2PyErr();
+      __PYX_ERR(0, 4280, __pyx_L1_error)
+    }
+
+    /* "pywrapfst.pyx":4279
+ *     """
+ *     cdef vector[string] filename_strings
+ *     for filename in filenames:             # <<<<<<<<<<<<<<
+ *       filename_strings.push_back(tostring(filename))
+ *     cdef unique_ptr[fst.FarReaderClass] tfar
+ */
   }
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF_SET(__pyx_v_filenames, __pyx_t_1);
-  __pyx_t_1 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":4259
- *     filenames = [tostring(filename) for filename in filenames]
+  /* "pywrapfst.pyx":4282
+ *       filename_strings.push_back(tostring(filename))
  *     cdef unique_ptr[fst.FarReaderClass] tfar
- *     tfar.reset(fst.FarReaderClass.Open(filenames))             # <<<<<<<<<<<<<<
+ *     tfar.reset(fst.FarReaderClass.Open(filename_strings))             # <<<<<<<<<<<<<<
  *     if tfar.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filenames))
  */
-  __pyx_t_6 = __pyx_convert_vector_from_py_std_3a__3a_string(__pyx_v_filenames); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4259, __pyx_L1_error)
-  __pyx_v_tfar.reset(fst::script::FarReaderClass::Open(__pyx_t_6));
+  __pyx_v_tfar.reset(fst::script::FarReaderClass::Open(__pyx_v_filename_strings));
 
-  /* "pywrapfst.pyx":4260
+  /* "pywrapfst.pyx":4283
  *     cdef unique_ptr[fst.FarReaderClass] tfar
- *     tfar.reset(fst.FarReaderClass.Open(filenames))
+ *     tfar.reset(fst.FarReaderClass.Open(filename_strings))
  *     if tfar.get() == NULL:             # <<<<<<<<<<<<<<
  *       raise FstIOError("Read failed: {!r}".format(filenames))
  *     cdef FarReader result = FarReader.__new__(FarReader)
  */
-  __pyx_t_7 = ((__pyx_v_tfar.get() == NULL) != 0);
-  if (unlikely(__pyx_t_7)) {
+  __pyx_t_5 = ((__pyx_v_tfar.get() == NULL) != 0);
+  if (unlikely(__pyx_t_5)) {
 
-    /* "pywrapfst.pyx":4261
- *     tfar.reset(fst.FarReaderClass.Open(filenames))
+    /* "pywrapfst.pyx":4284
+ *     tfar.reset(fst.FarReaderClass.Open(filename_strings))
  *     if tfar.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filenames))             # <<<<<<<<<<<<<<
  *     cdef FarReader result = FarReader.__new__(FarReader)
  *     result._reader.reset(tfar.release())
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4261, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 4261, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_9 = NULL;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) {
-      __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_8);
-      if (likely(__pyx_t_9)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
-        __Pyx_INCREF(__pyx_t_9);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_8, function);
-      }
-    }
-    if (!__pyx_t_9) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_v_filenames); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4261, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_8)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_filenames};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4261, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_filenames};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4261, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else
-      #endif
-      {
-        __pyx_t_10 = PyTuple_New(1+1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 4261, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_10);
-        __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_9); __pyx_t_9 = NULL;
-        __Pyx_INCREF(__pyx_v_filenames);
-        __Pyx_GIVEREF(__pyx_v_filenames);
-        PyTuple_SET_ITEM(__pyx_t_10, 0+1, __pyx_v_filenames);
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_10, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4261, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-      }
-    }
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4284, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Read_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4284, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
     __pyx_t_8 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_2);
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
+      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7);
       if (likely(__pyx_t_8)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
         __Pyx_INCREF(__pyx_t_8);
         __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_2, function);
+        __Pyx_DECREF_SET(__pyx_t_7, function);
       }
     }
-    if (!__pyx_t_8) {
-      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4261, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_t_4};
-        __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4261, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_t_4};
-        __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4261, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_10 = PyTuple_New(1+1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 4261, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_10);
-        __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_8); __pyx_t_8 = NULL;
-        __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_10, 0+1, __pyx_t_4);
-        __pyx_t_4 = 0;
-        __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_10, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4261, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+    __pyx_t_6 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_filenames) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_filenames);
+    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4284, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __pyx_t_7 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_7)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_7);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
       }
     }
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_6);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4284, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_1, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 4261, __pyx_L1_error)
+    __PYX_ERR(0, 4284, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":4260
+    /* "pywrapfst.pyx":4283
  *     cdef unique_ptr[fst.FarReaderClass] tfar
- *     tfar.reset(fst.FarReaderClass.Open(filenames))
+ *     tfar.reset(fst.FarReaderClass.Open(filename_strings))
  *     if tfar.get() == NULL:             # <<<<<<<<<<<<<<
  *       raise FstIOError("Read failed: {!r}".format(filenames))
  *     cdef FarReader result = FarReader.__new__(FarReader)
  */
   }
 
-  /* "pywrapfst.pyx":4262
+  /* "pywrapfst.pyx":4285
  *     if tfar.get() == NULL:
  *       raise FstIOError("Read failed: {!r}".format(filenames))
  *     cdef FarReader result = FarReader.__new__(FarReader)             # <<<<<<<<<<<<<<
  *     result._reader.reset(tfar.release())
  *     return result
  */
-  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_FarReader(((PyTypeObject *)__pyx_ptype_9pywrapfst_FarReader), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4262, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_tp_new_9pywrapfst_FarReader(((PyTypeObject *)__pyx_ptype_9pywrapfst_FarReader), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4285, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_FarReader *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":4263
+  /* "pywrapfst.pyx":4286
  *       raise FstIOError("Read failed: {!r}".format(filenames))
  *     cdef FarReader result = FarReader.__new__(FarReader)
  *     result._reader.reset(tfar.release())             # <<<<<<<<<<<<<<
@@ -43807,11 +42816,11 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_4open(CYTHON_UNUSED PyTypeObject
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4263, __pyx_L1_error)
+    __PYX_ERR(0, 4286, __pyx_L1_error)
   }
   __pyx_v_result->_reader.reset(__pyx_v_tfar.release());
 
-  /* "pywrapfst.pyx":4264
+  /* "pywrapfst.pyx":4287
  *     cdef FarReader result = FarReader.__new__(FarReader)
  *     result._reader.reset(tfar.release())
  *     return result             # <<<<<<<<<<<<<<
@@ -43823,7 +42832,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_4open(CYTHON_UNUSED PyTypeObject
   __pyx_r = ((PyObject *)__pyx_v_result);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4239
+  /* "pywrapfst.pyx":4260
  * 
  *   @classmethod
  *   def open(cls, *filenames):             # <<<<<<<<<<<<<<
@@ -43834,23 +42843,21 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_4open(CYTHON_UNUSED PyTypeObject
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_XDECREF(__pyx_t_10);
   __Pyx_AddTraceback("pywrapfst.FarReader.open", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_filenames);
-  __Pyx_XDECREF((PyObject *)__pyx_v_result);
   __Pyx_XDECREF(__pyx_v_filename);
+  __Pyx_XDECREF((PyObject *)__pyx_v_result);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4266
+/* "pywrapfst.pyx":4289
  *     return result
  * 
  *   cpdef string arc_type(self):             # <<<<<<<<<<<<<<
@@ -43871,39 +42878,52 @@ static std::string __pyx_f_9pywrapfst_9FarReader_arc_type(struct __pyx_obj_9pywr
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4266, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_7arc_type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4289, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarReader_7arc_type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4289, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4289, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4266, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4266, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4266, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4272
+  /* "pywrapfst.pyx":4295
  *     Returns a string indicating the arc type.
  *     """
  *     return self._reader.get().ArcType()             # <<<<<<<<<<<<<<
@@ -43912,12 +42932,12 @@ static std::string __pyx_f_9pywrapfst_9FarReader_arc_type(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4272, __pyx_L1_error)
+    __PYX_ERR(0, 4295, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_reader.get()->ArcType();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4266
+  /* "pywrapfst.pyx":4289
  *     return result
  * 
  *   cpdef string arc_type(self):             # <<<<<<<<<<<<<<
@@ -43958,7 +42978,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_6arc_type(struct __pyx_obj_9pywr
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("arc_type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarReader_arc_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4266, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarReader_arc_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4289, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -43975,7 +42995,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_6arc_type(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4274
+/* "pywrapfst.pyx":4297
  *     return self._reader.get().ArcType()
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -43996,39 +43016,52 @@ static bool __pyx_f_9pywrapfst_9FarReader_done(struct __pyx_obj_9pywrapfst_FarRe
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4274, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_9done)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_done); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4297, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarReader_9done)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4297, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4297, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4274, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4274, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4274, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4283
+  /* "pywrapfst.pyx":4306
  *       True if the iterator is exhausted, False otherwise.
  *     """
  *     return self._reader.get().Done()             # <<<<<<<<<<<<<<
@@ -44037,12 +43070,12 @@ static bool __pyx_f_9pywrapfst_9FarReader_done(struct __pyx_obj_9pywrapfst_FarRe
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4283, __pyx_L1_error)
+    __PYX_ERR(0, 4306, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_reader.get()->Done();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4274
+  /* "pywrapfst.pyx":4297
  *     return self._reader.get().ArcType()
  * 
  *   cpdef bool done(self):             # <<<<<<<<<<<<<<
@@ -44083,7 +43116,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_8done(struct __pyx_obj_9pywrapfs
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("done", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_9FarReader_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4274, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_9FarReader_done(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4297, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -44100,7 +43133,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_8done(struct __pyx_obj_9pywrapfs
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4285
+/* "pywrapfst.pyx":4308
  *     return self._reader.get().Done()
  * 
  *   cpdef bool error(self):             # <<<<<<<<<<<<<<
@@ -44121,39 +43154,52 @@ static bool __pyx_f_9pywrapfst_9FarReader_error(struct __pyx_obj_9pywrapfst_FarR
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_error); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4285, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_11error)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_error); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4308, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarReader_11error)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4308, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4308, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4285, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4285, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4285, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4294
+  /* "pywrapfst.pyx":4317
  *       True if the FarReader is in an errorful state, False otherwise.
  *     """
  *     return self._reader.get().Error()             # <<<<<<<<<<<<<<
@@ -44162,12 +43208,12 @@ static bool __pyx_f_9pywrapfst_9FarReader_error(struct __pyx_obj_9pywrapfst_FarR
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4294, __pyx_L1_error)
+    __PYX_ERR(0, 4317, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_reader.get()->Error();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4285
+  /* "pywrapfst.pyx":4308
  *     return self._reader.get().Done()
  * 
  *   cpdef bool error(self):             # <<<<<<<<<<<<<<
@@ -44208,7 +43254,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_10error(struct __pyx_obj_9pywrap
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("error", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_9FarReader_error(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4285, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_9FarReader_error(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4308, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -44225,7 +43271,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_10error(struct __pyx_obj_9pywrap
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4296
+/* "pywrapfst.pyx":4319
  *     return self._reader.get().Error()
  * 
  *   cpdef string far_type(self):             # <<<<<<<<<<<<<<
@@ -44246,39 +43292,52 @@ static std::string __pyx_f_9pywrapfst_9FarReader_far_type(struct __pyx_obj_9pywr
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_far_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4296, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_13far_type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_far_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4319, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarReader_13far_type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4319, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4319, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4296, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4296, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4296, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4297
+  /* "pywrapfst.pyx":4320
  * 
  *   cpdef string far_type(self):
  *     return fst.GetFarTypeString(self._reader.get().Type())             # <<<<<<<<<<<<<<
@@ -44287,12 +43346,12 @@ static std::string __pyx_f_9pywrapfst_9FarReader_far_type(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4297, __pyx_L1_error)
+    __PYX_ERR(0, 4320, __pyx_L1_error)
   }
   __pyx_r = fst::GetFarTypeString(__pyx_v_self->_reader.get()->Type());
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4296
+  /* "pywrapfst.pyx":4319
  *     return self._reader.get().Error()
  * 
  *   cpdef string far_type(self):             # <<<<<<<<<<<<<<
@@ -44332,7 +43391,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_12far_type(struct __pyx_obj_9pyw
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("far_type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarReader_far_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4296, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarReader_far_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4319, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -44349,7 +43408,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_12far_type(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4299
+/* "pywrapfst.pyx":4322
  *     return fst.GetFarTypeString(self._reader.get().Type())
  * 
  *   cpdef bool find(self, key) except *:             # <<<<<<<<<<<<<<
@@ -44365,71 +43424,58 @@ static bool __pyx_f_9pywrapfst_9FarReader_find(struct __pyx_obj_9pywrapfst_FarRe
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  bool __pyx_t_6;
-  std::string __pyx_t_7;
+  bool __pyx_t_5;
+  std::string __pyx_t_6;
   __Pyx_RefNannySetupContext("find", 0);
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_find); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4299, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_15find)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_find); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4322, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarReader_15find)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
-      }
-      if (!__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_key); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4299, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_key) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_key);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4322, __pyx_L1_error)
         __Pyx_GOTREF(__pyx_t_2);
-      } else {
-        #if CYTHON_FAST_PYCALL
-        if (PyFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_key};
-          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4299, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        #if CYTHON_FAST_PYCCALL
-        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-          PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_v_key};
-          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4299, __pyx_L1_error)
-          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_GOTREF(__pyx_t_2);
-        } else
-        #endif
-        {
-          __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4299, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
-          __Pyx_INCREF(__pyx_v_key);
-          __Pyx_GIVEREF(__pyx_v_key);
-          PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_v_key);
-          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4299, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4322, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_6 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4299, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_6;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4312
+  /* "pywrapfst.pyx":4335
  *       True if the key was found, False otherwise.
  *     """
  *     return self._reader.get().Find(tostring(key))             # <<<<<<<<<<<<<<
@@ -44438,13 +43484,13 @@ static bool __pyx_f_9pywrapfst_9FarReader_find(struct __pyx_obj_9pywrapfst_FarRe
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4312, __pyx_L1_error)
+    __PYX_ERR(0, 4335, __pyx_L1_error)
   }
-  __pyx_t_7 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4312, __pyx_L1_error)
-  __pyx_r = __pyx_v_self->_reader.get()->Find(__pyx_t_7);
+  __pyx_t_6 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4335, __pyx_L1_error)
+  __pyx_r = __pyx_v_self->_reader.get()->Find(__pyx_t_6);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4299
+  /* "pywrapfst.pyx":4322
  *     return fst.GetFarTypeString(self._reader.get().Type())
  * 
  *   cpdef bool find(self, key) except *:             # <<<<<<<<<<<<<<
@@ -44458,7 +43504,6 @@ static bool __pyx_f_9pywrapfst_9FarReader_find(struct __pyx_obj_9pywrapfst_FarRe
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("pywrapfst.FarReader.find", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -44487,8 +43532,8 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_14find(struct __pyx_obj_9pywrapf
   PyObject *__pyx_t_2 = NULL;
   __Pyx_RefNannySetupContext("find", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_9pywrapfst_9FarReader_find(__pyx_v_self, __pyx_v_key, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4299, __pyx_L1_error)
-  __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4299, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_9FarReader_find(__pyx_v_self, __pyx_v_key, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4322, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4322, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -44505,7 +43550,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_14find(struct __pyx_obj_9pywrapf
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4314
+/* "pywrapfst.pyx":4337
  *     return self._reader.get().Find(tostring(key))
  * 
  *   cpdef _Fst get_fst(self):             # <<<<<<<<<<<<<<
@@ -44525,40 +43570,53 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_9FarReader_get_fst(s
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_fst); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4314, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_17get_fst)) {
-      __Pyx_XDECREF(((PyObject *)__pyx_r));
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_fst); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4337, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarReader_17get_fst)) {
+        __Pyx_XDECREF(((PyObject *)__pyx_r));
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4337, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 4337, __pyx_L1_error)
+        __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
+        __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4314, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4314, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_9pywrapfst__Fst))))) __PYX_ERR(0, 4314, __pyx_L1_error)
-      __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_2);
-      __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4323
+  /* "pywrapfst.pyx":4346
  *       A copy of the FST at the current position.
  *     """
  *     return _init_XFst(new fst.FstClass(             # <<<<<<<<<<<<<<
@@ -44567,7 +43625,7 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_9FarReader_get_fst(s
  */
   __Pyx_XDECREF(((PyObject *)__pyx_r));
 
-  /* "pywrapfst.pyx":4324
+  /* "pywrapfst.pyx":4347
  *     """
  *     return _init_XFst(new fst.FstClass(
  *         deref(self._reader.get().GetFstClass())))             # <<<<<<<<<<<<<<
@@ -44576,23 +43634,23 @@ static struct __pyx_obj_9pywrapfst__Fst *__pyx_f_9pywrapfst_9FarReader_get_fst(s
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4324, __pyx_L1_error)
+    __PYX_ERR(0, 4347, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":4323
+  /* "pywrapfst.pyx":4346
  *       A copy of the FST at the current position.
  *     """
  *     return _init_XFst(new fst.FstClass(             # <<<<<<<<<<<<<<
  *         deref(self._reader.get().GetFstClass())))
  * 
  */
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(new fst::script::FstClass((*__pyx_v_self->_reader.get()->GetFstClass())))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4323, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst__init_XFst(new fst::script::FstClass((*__pyx_v_self->_reader.get()->GetFstClass())))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4346, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_t_1);
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4314
+  /* "pywrapfst.pyx":4337
  *     return self._reader.get().Find(tostring(key))
  * 
  *   cpdef _Fst get_fst(self):             # <<<<<<<<<<<<<<
@@ -44634,7 +43692,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_16get_fst(struct __pyx_obj_9pywr
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("get_fst", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_9FarReader_get_fst(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4314, __pyx_L1_error)
+  __pyx_t_1 = ((PyObject *)__pyx_f_9pywrapfst_9FarReader_get_fst(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4337, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -44651,7 +43709,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_16get_fst(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4326
+/* "pywrapfst.pyx":4349
  *         deref(self._reader.get().GetFstClass())))
  * 
  *   cpdef string get_key(self):             # <<<<<<<<<<<<<<
@@ -44672,39 +43730,52 @@ static std::string __pyx_f_9pywrapfst_9FarReader_get_key(struct __pyx_obj_9pywra
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4326, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_19get_key)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4349, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarReader_19get_key)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4349, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4349, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4326, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4326, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4326, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4335
+  /* "pywrapfst.pyx":4358
  *       The string key at the current position.
  *     """
  *     return self._reader.get().GetKey()             # <<<<<<<<<<<<<<
@@ -44713,12 +43784,12 @@ static std::string __pyx_f_9pywrapfst_9FarReader_get_key(struct __pyx_obj_9pywra
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4335, __pyx_L1_error)
+    __PYX_ERR(0, 4358, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_reader.get()->GetKey();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4326
+  /* "pywrapfst.pyx":4349
  *         deref(self._reader.get().GetFstClass())))
  * 
  *   cpdef string get_key(self):             # <<<<<<<<<<<<<<
@@ -44759,7 +43830,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_18get_key(struct __pyx_obj_9pywr
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("get_key", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarReader_get_key(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4326, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarReader_get_key(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4349, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -44776,7 +43847,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_18get_key(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4337
+/* "pywrapfst.pyx":4360
  *     return self._reader.get().GetKey()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -44795,37 +43866,50 @@ static void __pyx_f_9pywrapfst_9FarReader_next(struct __pyx_obj_9pywrapfst_FarRe
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4337, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_21next)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_next); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4360, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarReader_21next)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4360, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4337, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4337, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4343
+  /* "pywrapfst.pyx":4366
  *     Advances the iterator.
  *     """
  *     self._reader.get().Next()             # <<<<<<<<<<<<<<
@@ -44834,11 +43918,11 @@ static void __pyx_f_9pywrapfst_9FarReader_next(struct __pyx_obj_9pywrapfst_FarRe
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4343, __pyx_L1_error)
+    __PYX_ERR(0, 4366, __pyx_L1_error)
   }
   __pyx_v_self->_reader.get()->Next();
 
-  /* "pywrapfst.pyx":4337
+  /* "pywrapfst.pyx":4360
  *     return self._reader.get().GetKey()
  * 
  *   cpdef void next(self):             # <<<<<<<<<<<<<<
@@ -44878,7 +43962,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_20next(struct __pyx_obj_9pywrapf
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("next", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_9FarReader_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4337, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_9FarReader_next(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4360, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -44895,7 +43979,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_20next(struct __pyx_obj_9pywrapf
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4345
+/* "pywrapfst.pyx":4368
  *     self._reader.get().Next()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -44914,37 +43998,50 @@ static void __pyx_f_9pywrapfst_9FarReader_reset(struct __pyx_obj_9pywrapfst_FarR
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4345, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_23reset)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_reset); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4368, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarReader_23reset)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4368, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4345, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4345, __pyx_L1_error)
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4351
+  /* "pywrapfst.pyx":4374
  *     Resets the iterator to the initial position.
  *     """
  *     self._reader.get().Reset()             # <<<<<<<<<<<<<<
@@ -44953,11 +44050,11 @@ static void __pyx_f_9pywrapfst_9FarReader_reset(struct __pyx_obj_9pywrapfst_FarR
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4351, __pyx_L1_error)
+    __PYX_ERR(0, 4374, __pyx_L1_error)
   }
   __pyx_v_self->_reader.get()->Reset();
 
-  /* "pywrapfst.pyx":4345
+  /* "pywrapfst.pyx":4368
  *     self._reader.get().Next()
  * 
  *   cpdef void reset(self):             # <<<<<<<<<<<<<<
@@ -44997,7 +44094,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_22reset(struct __pyx_obj_9pywrap
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("reset", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_9FarReader_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4345, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(__pyx_f_9pywrapfst_9FarReader_reset(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4368, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -45014,12 +44111,12 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_22reset(struct __pyx_obj_9pywrap
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4353
+/* "pywrapfst.pyx":4376
  *     self._reader.get().Reset()
  * 
  *   def __getitem__(self, key):             # <<<<<<<<<<<<<<
- *     cdef string ckey = tostring(key)
- *     if self.get_key() == ckey or self._reader.get().Find(ckey):
+ *     if self._reader.get().Find(tostring(key)):
+ *       return self.get_fst()
  */
 
 /* Python wrapper */
@@ -45036,54 +44133,31 @@ static PyObject *__pyx_pw_9pywrapfst_9FarReader_25__getitem__(PyObject *__pyx_v_
 }
 
 static PyObject *__pyx_pf_9pywrapfst_9FarReader_24__getitem__(struct __pyx_obj_9pywrapfst_FarReader *__pyx_v_self, PyObject *__pyx_v_key) {
-  std::string __pyx_v_ckey;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   std::string __pyx_t_1;
   int __pyx_t_2;
-  int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_3 = NULL;
   __Pyx_RefNannySetupContext("__getitem__", 0);
 
-  /* "pywrapfst.pyx":4354
+  /* "pywrapfst.pyx":4377
  * 
  *   def __getitem__(self, key):
- *     cdef string ckey = tostring(key)             # <<<<<<<<<<<<<<
- *     if self.get_key() == ckey or self._reader.get().Find(ckey):
- *       return self.get_fst()
- */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4354, __pyx_L1_error)
-  __pyx_v_ckey = __pyx_t_1;
-
-  /* "pywrapfst.pyx":4355
- *   def __getitem__(self, key):
- *     cdef string ckey = tostring(key)
- *     if self.get_key() == ckey or self._reader.get().Find(ckey):             # <<<<<<<<<<<<<<
+ *     if self._reader.get().Find(tostring(key)):             # <<<<<<<<<<<<<<
  *       return self.get_fst()
  *     else:
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "get_key");
-    __PYX_ERR(0, 4355, __pyx_L1_error)
-  }
-  __pyx_t_3 = ((((struct __pyx_vtabstruct_9pywrapfst_FarReader *)__pyx_v_self->__pyx_vtab)->get_key(__pyx_v_self, 0) == __pyx_v_ckey) != 0);
-  if (!__pyx_t_3) {
-  } else {
-    __pyx_t_2 = __pyx_t_3;
-    goto __pyx_L4_bool_binop_done;
-  }
-  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_reader");
-    __PYX_ERR(0, 4355, __pyx_L1_error)
+    __PYX_ERR(0, 4377, __pyx_L1_error)
   }
-  __pyx_t_3 = (__pyx_v_self->_reader.get()->Find(__pyx_v_ckey) != 0);
-  __pyx_t_2 = __pyx_t_3;
-  __pyx_L4_bool_binop_done:;
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4377, __pyx_L1_error)
+  __pyx_t_2 = (__pyx_v_self->_reader.get()->Find(__pyx_t_1) != 0);
   if (likely(__pyx_t_2)) {
 
-    /* "pywrapfst.pyx":4356
- *     cdef string ckey = tostring(key)
- *     if self.get_key() == ckey or self._reader.get().Find(ckey):
+    /* "pywrapfst.pyx":4378
+ *   def __getitem__(self, key):
+ *     if self._reader.get().Find(tostring(key)):
  *       return self.get_fst()             # <<<<<<<<<<<<<<
  *     else:
  *       raise KeyError(key)
@@ -45091,24 +44165,24 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_24__getitem__(struct __pyx_obj_9
     __Pyx_XDECREF(__pyx_r);
     if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
       PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "get_fst");
-      __PYX_ERR(0, 4356, __pyx_L1_error)
+      __PYX_ERR(0, 4378, __pyx_L1_error)
     }
-    __pyx_t_4 = ((PyObject *)((struct __pyx_vtabstruct_9pywrapfst_FarReader *)__pyx_v_self->__pyx_vtab)->get_fst(__pyx_v_self, 0)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4356, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_r = __pyx_t_4;
-    __pyx_t_4 = 0;
+    __pyx_t_3 = ((PyObject *)((struct __pyx_vtabstruct_9pywrapfst_FarReader *)__pyx_v_self->__pyx_vtab)->get_fst(__pyx_v_self, 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4378, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_r = __pyx_t_3;
+    __pyx_t_3 = 0;
     goto __pyx_L0;
 
-    /* "pywrapfst.pyx":4355
+    /* "pywrapfst.pyx":4377
+ * 
  *   def __getitem__(self, key):
- *     cdef string ckey = tostring(key)
- *     if self.get_key() == ckey or self._reader.get().Find(ckey):             # <<<<<<<<<<<<<<
+ *     if self._reader.get().Find(tostring(key)):             # <<<<<<<<<<<<<<
  *       return self.get_fst()
  *     else:
  */
   }
 
-  /* "pywrapfst.pyx":4358
+  /* "pywrapfst.pyx":4380
  *       return self.get_fst()
  *     else:
  *       raise KeyError(key)             # <<<<<<<<<<<<<<
@@ -45116,24 +44190,24 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_24__getitem__(struct __pyx_obj_9
  * 
  */
   /*else*/ {
-    __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_KeyError, __pyx_v_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4358, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __PYX_ERR(0, 4358, __pyx_L1_error)
+    __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_KeyError, __pyx_v_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4380, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __PYX_ERR(0, 4380, __pyx_L1_error)
   }
 
-  /* "pywrapfst.pyx":4353
+  /* "pywrapfst.pyx":4376
  *     self._reader.get().Reset()
  * 
  *   def __getitem__(self, key):             # <<<<<<<<<<<<<<
- *     cdef string ckey = tostring(key)
- *     if self.get_key() == ckey or self._reader.get().Find(ckey):
+ *     if self._reader.get().Find(tostring(key)):
+ *       return self.get_fst()
  */
 
   /* function exit code */
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_AddTraceback("pywrapfst.FarReader.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -45173,7 +44247,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_26__reduce_cython__(CYTHON_UNUSE
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._reader cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__93, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__56, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -45226,7 +44300,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_28__setstate_cython__(CYTHON_UNU
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._reader cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__94, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__57, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -45249,7 +44323,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarReader_28__setstate_cython__(CYTHON_UNU
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4381
+/* "pywrapfst.pyx":4403
  *   """
  * 
  *   def __init__(self):             # <<<<<<<<<<<<<<
@@ -45282,31 +44356,30 @@ static int __pyx_pf_9pywrapfst_9FarWriter___init__(struct __pyx_obj_9pywrapfst_F
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
-  PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "pywrapfst.pyx":4382
+  /* "pywrapfst.pyx":4404
  * 
  *   def __init__(self):
  *     raise FstDeletedConstructorError(             # <<<<<<<<<<<<<<
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstDeletedConstructorError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4382, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstDeletedConstructorError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4404, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
 
-  /* "pywrapfst.pyx":4383
+  /* "pywrapfst.pyx":4405
  *   def __init__(self):
  *     raise FstDeletedConstructorError(
  *         "Cannot construct {}".format(self.__class__.__name__))             # <<<<<<<<<<<<<<
  * 
  *   def __repr__(self):
  */
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Cannot_construct, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4383, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Cannot_construct, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4405, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_class); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4383, __pyx_L1_error)
+  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_class); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4405, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4383, __pyx_L1_error)
+  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4405, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __pyx_t_5 = NULL;
@@ -45319,41 +44392,11 @@ static int __pyx_pf_9pywrapfst_9FarWriter___init__(struct __pyx_obj_9pywrapfst_F
       __Pyx_DECREF_SET(__pyx_t_4, function);
     }
   }
-  if (!__pyx_t_5) {
-    __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4383, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_GOTREF(__pyx_t_3);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_6};
-      __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4383, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_6};
-      __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4383, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4383, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
-      __Pyx_GIVEREF(__pyx_t_6);
-      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_t_6);
-      __pyx_t_6 = 0;
-      __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4383, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    }
-  }
+  __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4405, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
@@ -45365,47 +44408,17 @@ static int __pyx_pf_9pywrapfst_9FarWriter___init__(struct __pyx_obj_9pywrapfst_F
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  if (!__pyx_t_4) {
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4382, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-  } else {
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4382, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4382, __pyx_L1_error)
-      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4382, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_4); __pyx_t_4 = NULL;
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4382, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    }
-  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4404, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __PYX_ERR(0, 4382, __pyx_L1_error)
+  __PYX_ERR(0, 4404, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":4381
+  /* "pywrapfst.pyx":4403
  *   """
  * 
  *   def __init__(self):             # <<<<<<<<<<<<<<
@@ -45421,14 +44434,13 @@ static int __pyx_pf_9pywrapfst_9FarWriter___init__(struct __pyx_obj_9pywrapfst_F
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_AddTraceback("pywrapfst.FarWriter.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = -1;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4385
+/* "pywrapfst.pyx":4407
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -45461,7 +44473,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_2__repr__(struct __pyx_obj_9pywr
   PyObject *__pyx_t_7 = NULL;
   __Pyx_RefNannySetupContext("__repr__", 0);
 
-  /* "pywrapfst.pyx":4386
+  /* "pywrapfst.pyx":4408
  * 
  *   def __repr__(self):
  *     return "<{} FarWriter at 0x{:x}>".format(self.far_type(), id(self))             # <<<<<<<<<<<<<<
@@ -45469,15 +44481,15 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_2__repr__(struct __pyx_obj_9pywr
  *   @classmethod
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_FarWriter_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4386, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_FarWriter_at_0x_x, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4408, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "far_type");
-    __PYX_ERR(0, 4386, __pyx_L1_error)
+    __PYX_ERR(0, 4408, __pyx_L1_error)
   }
-  __pyx_t_3 = __pyx_convert_PyBytes_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_FarWriter *)__pyx_v_self->__pyx_vtab)->far_type(__pyx_v_self, 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4386, __pyx_L1_error)
+  __pyx_t_3 = __pyx_convert_PyUnicode_string_to_py_std__in_string(((struct __pyx_vtabstruct_9pywrapfst_FarWriter *)__pyx_v_self->__pyx_vtab)->far_type(__pyx_v_self, 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4408, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4386, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4408, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __pyx_t_5 = NULL;
   __pyx_t_6 = 0;
@@ -45494,7 +44506,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_2__repr__(struct __pyx_obj_9pywr
   #if CYTHON_FAST_PYCALL
   if (PyFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4386, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4408, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -45504,7 +44516,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_2__repr__(struct __pyx_obj_9pywr
   #if CYTHON_FAST_PYCCALL
   if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
     PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, __pyx_t_4};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4386, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4408, __pyx_L1_error)
     __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -45512,7 +44524,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_2__repr__(struct __pyx_obj_9pywr
   } else
   #endif
   {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4386, __pyx_L1_error)
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4408, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_7);
     if (__pyx_t_5) {
       __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
@@ -45523,7 +44535,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_2__repr__(struct __pyx_obj_9pywr
     PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_4);
     __pyx_t_3 = 0;
     __pyx_t_4 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4386, __pyx_L1_error)
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4408, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   }
@@ -45532,7 +44544,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_2__repr__(struct __pyx_obj_9pywr
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4385
+  /* "pywrapfst.pyx":4407
  *         "Cannot construct {}".format(self.__class__.__name__))
  * 
  *   def __repr__(self):             # <<<<<<<<<<<<<<
@@ -45556,7 +44568,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_2__repr__(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4389
+/* "pywrapfst.pyx":4411
  * 
  *   @classmethod
  *   def create(cls, filename, arc_type=b"standard", far_type=b"default"):             # <<<<<<<<<<<<<<
@@ -45611,7 +44623,7 @@ static PyObject *__pyx_pw_9pywrapfst_9FarWriter_5create(PyObject *__pyx_v_cls, P
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "create") < 0)) __PYX_ERR(0, 4389, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "create") < 0)) __PYX_ERR(0, 4411, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -45630,7 +44642,7 @@ static PyObject *__pyx_pw_9pywrapfst_9FarWriter_5create(PyObject *__pyx_v_cls, P
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("create", 0, 1, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4389, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("create", 0, 1, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4411, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.FarWriter.create", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -45657,30 +44669,29 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
   PyObject *__pyx_t_6 = NULL;
   PyObject *__pyx_t_7 = NULL;
   PyObject *__pyx_t_8 = NULL;
-  PyObject *__pyx_t_9 = NULL;
   __Pyx_RefNannySetupContext("create", 0);
 
-  /* "pywrapfst.pyx":4410
+  /* "pywrapfst.pyx":4432
  *       FstIOError: Read failed.
  *     """
  *     cdef fst.FarType ft = fst.GetFarType(tostring(far_type))             # <<<<<<<<<<<<<<
  *     cdef fst.FarWriterClass *tfar = fst.FarWriterClass.Create(
  *         tostring(filename), tostring(arc_type), ft)
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_far_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4410, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_far_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4432, __pyx_L1_error)
   __pyx_v_ft = fst::script::GetFarType(__pyx_t_1);
 
-  /* "pywrapfst.pyx":4412
+  /* "pywrapfst.pyx":4434
  *     cdef fst.FarType ft = fst.GetFarType(tostring(far_type))
  *     cdef fst.FarWriterClass *tfar = fst.FarWriterClass.Create(
  *         tostring(filename), tostring(arc_type), ft)             # <<<<<<<<<<<<<<
  *     if tfar == NULL:
  *       raise FstIOError("Open failed: {!r}".format(filename))
  */
-  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4412, __pyx_L1_error)
-  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_arc_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4412, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9pywrapfst_tostring(__pyx_v_filename, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4434, __pyx_L1_error)
+  __pyx_t_2 = __pyx_f_9pywrapfst_tostring(__pyx_v_arc_type, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4434, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":4411
+  /* "pywrapfst.pyx":4433
  *     """
  *     cdef fst.FarType ft = fst.GetFarType(tostring(far_type))
  *     cdef fst.FarWriterClass *tfar = fst.FarWriterClass.Create(             # <<<<<<<<<<<<<<
@@ -45689,7 +44700,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
  */
   __pyx_v_tfar = fst::script::FarWriterClass::Create(__pyx_t_1, __pyx_t_2, __pyx_v_ft);
 
-  /* "pywrapfst.pyx":4413
+  /* "pywrapfst.pyx":4435
  *     cdef fst.FarWriterClass *tfar = fst.FarWriterClass.Create(
  *         tostring(filename), tostring(arc_type), ft)
  *     if tfar == NULL:             # <<<<<<<<<<<<<<
@@ -45699,16 +44710,16 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
   __pyx_t_3 = ((__pyx_v_tfar == NULL) != 0);
   if (unlikely(__pyx_t_3)) {
 
-    /* "pywrapfst.pyx":4414
+    /* "pywrapfst.pyx":4436
  *         tostring(filename), tostring(arc_type), ft)
  *     if tfar == NULL:
  *       raise FstIOError("Open failed: {!r}".format(filename))             # <<<<<<<<<<<<<<
  *     cdef FarWriter result = FarWriter.__new__(FarWriter)
  *     result._writer.reset(tfar)
  */
-    __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstIOError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4414, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_FstIOError); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4436, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Open_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4414, __pyx_L1_error)
+    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_Open_failed_r, __pyx_n_s_format); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4436, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_7);
     __pyx_t_8 = NULL;
     if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
@@ -45720,38 +44731,10 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
         __Pyx_DECREF_SET(__pyx_t_7, function);
       }
     }
-    if (!__pyx_t_8) {
-      __pyx_t_6 = __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_filename); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4414, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_6);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_7)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_filename};
-        __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4414, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_GOTREF(__pyx_t_6);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_v_filename};
-        __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4414, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_GOTREF(__pyx_t_6);
-      } else
-      #endif
-      {
-        __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 4414, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_9);
-        __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_8); __pyx_t_8 = NULL;
-        __Pyx_INCREF(__pyx_v_filename);
-        __Pyx_GIVEREF(__pyx_v_filename);
-        PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_v_filename);
-        __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_9, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4414, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      }
-    }
+    __pyx_t_6 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_filename);
+    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4436, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
     __pyx_t_7 = NULL;
     if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
@@ -45763,47 +44746,17 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
         __Pyx_DECREF_SET(__pyx_t_5, function);
       }
     }
-    if (!__pyx_t_7) {
-      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4414, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_GOTREF(__pyx_t_4);
-    } else {
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4414, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-        PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_t_6};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4414, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 4414, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_9);
-        __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); __pyx_t_7 = NULL;
-        __Pyx_GIVEREF(__pyx_t_6);
-        PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_t_6);
-        __pyx_t_6 = 0;
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4414, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      }
-    }
+    __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4436, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_Raise(__pyx_t_4, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __PYX_ERR(0, 4414, __pyx_L1_error)
+    __PYX_ERR(0, 4436, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":4413
+    /* "pywrapfst.pyx":4435
  *     cdef fst.FarWriterClass *tfar = fst.FarWriterClass.Create(
  *         tostring(filename), tostring(arc_type), ft)
  *     if tfar == NULL:             # <<<<<<<<<<<<<<
@@ -45812,19 +44765,19 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
  */
   }
 
-  /* "pywrapfst.pyx":4415
+  /* "pywrapfst.pyx":4437
  *     if tfar == NULL:
  *       raise FstIOError("Open failed: {!r}".format(filename))
  *     cdef FarWriter result = FarWriter.__new__(FarWriter)             # <<<<<<<<<<<<<<
  *     result._writer.reset(tfar)
  *     return result
  */
-  __pyx_t_4 = ((PyObject *)__pyx_tp_new_9pywrapfst_FarWriter(((PyTypeObject *)__pyx_ptype_9pywrapfst_FarWriter), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4415, __pyx_L1_error)
+  __pyx_t_4 = ((PyObject *)__pyx_tp_new_9pywrapfst_FarWriter(((PyTypeObject *)__pyx_ptype_9pywrapfst_FarWriter), __pyx_empty_tuple, NULL)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4437, __pyx_L1_error)
   __Pyx_GOTREF(((PyObject *)__pyx_t_4));
   __pyx_v_result = ((struct __pyx_obj_9pywrapfst_FarWriter *)__pyx_t_4);
   __pyx_t_4 = 0;
 
-  /* "pywrapfst.pyx":4416
+  /* "pywrapfst.pyx":4438
  *       raise FstIOError("Open failed: {!r}".format(filename))
  *     cdef FarWriter result = FarWriter.__new__(FarWriter)
  *     result._writer.reset(tfar)             # <<<<<<<<<<<<<<
@@ -45833,11 +44786,11 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
  */
   if (unlikely(((PyObject *)__pyx_v_result) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_writer");
-    __PYX_ERR(0, 4416, __pyx_L1_error)
+    __PYX_ERR(0, 4438, __pyx_L1_error)
   }
   __pyx_v_result->_writer.reset(__pyx_v_tfar);
 
-  /* "pywrapfst.pyx":4417
+  /* "pywrapfst.pyx":4439
  *     cdef FarWriter result = FarWriter.__new__(FarWriter)
  *     result._writer.reset(tfar)
  *     return result             # <<<<<<<<<<<<<<
@@ -45849,7 +44802,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
   __pyx_r = ((PyObject *)__pyx_v_result);
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4389
+  /* "pywrapfst.pyx":4411
  * 
  *   @classmethod
  *   def create(cls, filename, arc_type=b"standard", far_type=b"default"):             # <<<<<<<<<<<<<<
@@ -45864,7 +44817,6 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
   __Pyx_XDECREF(__pyx_t_6);
   __Pyx_XDECREF(__pyx_t_7);
   __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
   __Pyx_AddTraceback("pywrapfst.FarWriter.create", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -45874,7 +44826,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_4create(CYTHON_UNUSED PyTypeObje
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4421
+/* "pywrapfst.pyx":4443
  *   # NB: Invoking this method may be dangerous: calling any other method on the
  *   # instance after this is invoked may result in a null dereference.
  *   cdef void close(self):             # <<<<<<<<<<<<<<
@@ -45886,7 +44838,7 @@ static void __pyx_f_9pywrapfst_9FarWriter_close(struct __pyx_obj_9pywrapfst_FarW
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("close", 0);
 
-  /* "pywrapfst.pyx":4422
+  /* "pywrapfst.pyx":4444
  *   # instance after this is invoked may result in a null dereference.
  *   cdef void close(self):
  *     self._writer.reset()             # <<<<<<<<<<<<<<
@@ -45895,11 +44847,11 @@ static void __pyx_f_9pywrapfst_9FarWriter_close(struct __pyx_obj_9pywrapfst_FarW
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_writer");
-    __PYX_ERR(0, 4422, __pyx_L1_error)
+    __PYX_ERR(0, 4444, __pyx_L1_error)
   }
   __pyx_v_self->_writer.reset();
 
-  /* "pywrapfst.pyx":4421
+  /* "pywrapfst.pyx":4443
  *   # NB: Invoking this method may be dangerous: calling any other method on the
  *   # instance after this is invoked may result in a null dereference.
  *   cdef void close(self):             # <<<<<<<<<<<<<<
@@ -45915,7 +44867,7 @@ static void __pyx_f_9pywrapfst_9FarWriter_close(struct __pyx_obj_9pywrapfst_FarW
   __Pyx_RefNannyFinishContext();
 }
 
-/* "pywrapfst.pyx":4424
+/* "pywrapfst.pyx":4446
  *     self._writer.reset()
  * 
  *   cpdef void add(self, key, _Fst ifst) except *:             # <<<<<<<<<<<<<<
@@ -45938,64 +44890,80 @@ static void __pyx_f_9pywrapfst_9FarWriter_add(struct __pyx_obj_9pywrapfst_FarWri
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_add); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4424, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarWriter_7add)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      __pyx_t_5 = 0;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
-          __pyx_t_5 = 1;
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_add); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4446, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarWriter_7add)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        __pyx_t_5 = 0;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+            __pyx_t_5 = 1;
+          }
         }
+        #if CYTHON_FAST_PYCALL
+        if (PyFunction_Check(__pyx_t_3)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_key, ((PyObject *)__pyx_v_ifst)};
+          __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4446, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+        } else
+        #endif
+        #if CYTHON_FAST_PYCCALL
+        if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
+          PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_key, ((PyObject *)__pyx_v_ifst)};
+          __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4446, __pyx_L1_error)
+          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+          __Pyx_GOTREF(__pyx_t_2);
+        } else
+        #endif
+        {
+          __pyx_t_6 = PyTuple_New(2+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4446, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_6);
+          if (__pyx_t_4) {
+            __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); __pyx_t_4 = NULL;
+          }
+          __Pyx_INCREF(__pyx_v_key);
+          __Pyx_GIVEREF(__pyx_v_key);
+          PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_5, __pyx_v_key);
+          __Pyx_INCREF(((PyObject *)__pyx_v_ifst));
+          __Pyx_GIVEREF(((PyObject *)__pyx_v_ifst));
+          PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_5, ((PyObject *)__pyx_v_ifst));
+          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4446, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+        }
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
       }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_key, ((PyObject *)__pyx_v_ifst)};
-        __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4424, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_v_key, ((PyObject *)__pyx_v_ifst)};
-        __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4424, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_GOTREF(__pyx_t_2);
-      } else
-      #endif
-      {
-        __pyx_t_6 = PyTuple_New(2+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4424, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        if (__pyx_t_4) {
-          __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); __pyx_t_4 = NULL;
-        }
-        __Pyx_INCREF(__pyx_v_key);
-        __Pyx_GIVEREF(__pyx_v_key);
-        PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_5, __pyx_v_key);
-        __Pyx_INCREF(((PyObject *)__pyx_v_ifst));
-        __Pyx_GIVEREF(((PyObject *)__pyx_v_ifst));
-        PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_5, ((PyObject *)__pyx_v_ifst));
-        __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4424, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4443
+  /* "pywrapfst.pyx":4465
  *     # Failure here results from passing an FST with a different arc type than
  *     # used by the FAR was initialized to use.
  *     if not self._writer.get().Add(tostring(key), deref(ifst._fst)):             # <<<<<<<<<<<<<<
@@ -46004,33 +44972,45 @@ static void __pyx_f_9pywrapfst_9FarWriter_add(struct __pyx_obj_9pywrapfst_FarWri
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_writer");
-    __PYX_ERR(0, 4443, __pyx_L1_error)
+    __PYX_ERR(0, 4465, __pyx_L1_error)
   }
-  __pyx_t_7 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4443, __pyx_L1_error)
+  __pyx_t_7 = __pyx_f_9pywrapfst_tostring(__pyx_v_key, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4465, __pyx_L1_error)
   if (unlikely(((PyObject *)__pyx_v_ifst) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_fst");
-    __PYX_ERR(0, 4443, __pyx_L1_error)
+    __PYX_ERR(0, 4465, __pyx_L1_error)
   }
   __pyx_t_8 = ((!(__pyx_v_self->_writer.get()->Add(__pyx_t_7, (*__pyx_v_ifst->_fst)) != 0)) != 0);
   if (unlikely(__pyx_t_8)) {
 
-    /* "pywrapfst.pyx":4444
+    /* "pywrapfst.pyx":4466
  *     # used by the FAR was initialized to use.
  *     if not self._writer.get().Add(tostring(key), deref(ifst._fst)):
  *       raise FstOpError("Incompatible or invalid arc type")             # <<<<<<<<<<<<<<
  *     # An error here usually indicates a key out of order.
  *     if self._writer.get().Error():
  */
-    __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstOpError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4444, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__95, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4444, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstOpError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4466, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __pyx_t_3 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_3)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_kp_u_Incompatible_or_invalid_arc_type) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_kp_u_Incompatible_or_invalid_arc_type);
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4466, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 4444, __pyx_L1_error)
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 4466, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":4443
+    /* "pywrapfst.pyx":4465
  *     # Failure here results from passing an FST with a different arc type than
  *     # used by the FAR was initialized to use.
  *     if not self._writer.get().Add(tostring(key), deref(ifst._fst)):             # <<<<<<<<<<<<<<
@@ -46039,7 +45019,7 @@ static void __pyx_f_9pywrapfst_9FarWriter_add(struct __pyx_obj_9pywrapfst_FarWri
  */
   }
 
-  /* "pywrapfst.pyx":4446
+  /* "pywrapfst.pyx":4468
  *       raise FstOpError("Incompatible or invalid arc type")
  *     # An error here usually indicates a key out of order.
  *     if self._writer.get().Error():             # <<<<<<<<<<<<<<
@@ -46048,28 +45028,40 @@ static void __pyx_f_9pywrapfst_9FarWriter_add(struct __pyx_obj_9pywrapfst_FarWri
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_writer");
-    __PYX_ERR(0, 4446, __pyx_L1_error)
+    __PYX_ERR(0, 4468, __pyx_L1_error)
   }
   __pyx_t_8 = (__pyx_v_self->_writer.get()->Error() != 0);
   if (unlikely(__pyx_t_8)) {
 
-    /* "pywrapfst.pyx":4447
+    /* "pywrapfst.pyx":4469
  *     # An error here usually indicates a key out of order.
  *     if self._writer.get().Error():
  *       raise FstArgError("Key out of order")             # <<<<<<<<<<<<<<
  * 
  *   cpdef string arc_type(self):
  */
-    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstArgError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4447, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstArgError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4469, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__96, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4447, __pyx_L1_error)
+    __pyx_t_3 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_3)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_kp_u_Key_out_of_order) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_kp_u_Key_out_of_order);
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4469, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_Raise(__pyx_t_1, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 4447, __pyx_L1_error)
+    __PYX_ERR(0, 4469, __pyx_L1_error)
 
-    /* "pywrapfst.pyx":4446
+    /* "pywrapfst.pyx":4468
  *       raise FstOpError("Incompatible or invalid arc type")
  *     # An error here usually indicates a key out of order.
  *     if self._writer.get().Error():             # <<<<<<<<<<<<<<
@@ -46078,7 +45070,7 @@ static void __pyx_f_9pywrapfst_9FarWriter_add(struct __pyx_obj_9pywrapfst_FarWri
  */
   }
 
-  /* "pywrapfst.pyx":4424
+  /* "pywrapfst.pyx":4446
  *     self._writer.reset()
  * 
  *   cpdef void add(self, key, _Fst ifst) except *:             # <<<<<<<<<<<<<<
@@ -46131,11 +45123,11 @@ static PyObject *__pyx_pw_9pywrapfst_9FarWriter_7add(PyObject *__pyx_v_self, PyO
         case  1:
         if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ifst)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("add", 1, 2, 2, 1); __PYX_ERR(0, 4424, __pyx_L3_error)
+          __Pyx_RaiseArgtupleInvalid("add", 1, 2, 2, 1); __PYX_ERR(0, 4446, __pyx_L3_error)
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "add") < 0)) __PYX_ERR(0, 4424, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "add") < 0)) __PYX_ERR(0, 4446, __pyx_L3_error)
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -46148,13 +45140,13 @@ static PyObject *__pyx_pw_9pywrapfst_9FarWriter_7add(PyObject *__pyx_v_self, PyO
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("add", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4424, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("add", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4446, __pyx_L3_error)
   __pyx_L3_error:;
   __Pyx_AddTraceback("pywrapfst.FarWriter.add", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 4424, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_ifst), __pyx_ptype_9pywrapfst__Fst, 1, "ifst", 0))) __PYX_ERR(0, 4446, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_9FarWriter_6add(((struct __pyx_obj_9pywrapfst_FarWriter *)__pyx_v_self), __pyx_v_key, __pyx_v_ifst);
 
   /* function exit code */
@@ -46172,8 +45164,8 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_6add(struct __pyx_obj_9pywrapfst
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("add", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_f_9pywrapfst_9FarWriter_add(__pyx_v_self, __pyx_v_key, __pyx_v_ifst, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4424, __pyx_L1_error)
-  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4424, __pyx_L1_error)
+  __pyx_f_9pywrapfst_9FarWriter_add(__pyx_v_self, __pyx_v_key, __pyx_v_ifst, 1); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4446, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_void_to_None(NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4446, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -46190,7 +45182,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_6add(struct __pyx_obj_9pywrapfst
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4449
+/* "pywrapfst.pyx":4471
  *       raise FstArgError("Key out of order")
  * 
  *   cpdef string arc_type(self):             # <<<<<<<<<<<<<<
@@ -46211,39 +45203,52 @@ static std::string __pyx_f_9pywrapfst_9FarWriter_arc_type(struct __pyx_obj_9pywr
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4449, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarWriter_9arc_type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_arc_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4471, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarWriter_9arc_type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4471, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4471, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4449, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4449, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4449, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4455
+  /* "pywrapfst.pyx":4477
  *     Returns a string indicating the arc type.
  *     """
  *     return self._writer.get().ArcType()             # <<<<<<<<<<<<<<
@@ -46252,12 +45257,12 @@ static std::string __pyx_f_9pywrapfst_9FarWriter_arc_type(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_writer");
-    __PYX_ERR(0, 4455, __pyx_L1_error)
+    __PYX_ERR(0, 4477, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_writer.get()->ArcType();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4449
+  /* "pywrapfst.pyx":4471
  *       raise FstArgError("Key out of order")
  * 
  *   cpdef string arc_type(self):             # <<<<<<<<<<<<<<
@@ -46298,7 +45303,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_8arc_type(struct __pyx_obj_9pywr
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("arc_type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarWriter_arc_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4449, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarWriter_arc_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4471, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -46315,7 +45320,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_8arc_type(struct __pyx_obj_9pywr
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4457
+/* "pywrapfst.pyx":4479
  *     return self._writer.get().ArcType()
  * 
  *   cpdef bool error(self):             # <<<<<<<<<<<<<<
@@ -46336,39 +45341,52 @@ static bool __pyx_f_9pywrapfst_9FarWriter_error(struct __pyx_obj_9pywrapfst_FarW
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_error); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4457, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarWriter_11error)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_error); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4479, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarWriter_11error)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4479, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4479, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4457, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4457, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_5 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4457, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4466
+  /* "pywrapfst.pyx":4488
  *       True if the FarWriter is in an errorful state, False otherwise.
  *     """
  *     return self._writer.get().Error()             # <<<<<<<<<<<<<<
@@ -46377,12 +45395,12 @@ static bool __pyx_f_9pywrapfst_9FarWriter_error(struct __pyx_obj_9pywrapfst_FarW
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_writer");
-    __PYX_ERR(0, 4466, __pyx_L1_error)
+    __PYX_ERR(0, 4488, __pyx_L1_error)
   }
   __pyx_r = __pyx_v_self->_writer.get()->Error();
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4457
+  /* "pywrapfst.pyx":4479
  *     return self._writer.get().ArcType()
  * 
  *   cpdef bool error(self):             # <<<<<<<<<<<<<<
@@ -46423,7 +45441,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_10error(struct __pyx_obj_9pywrap
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("error", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_9FarWriter_error(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4457, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_f_9pywrapfst_9FarWriter_error(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4479, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -46440,7 +45458,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_10error(struct __pyx_obj_9pywrap
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4468
+/* "pywrapfst.pyx":4490
  *     return self._writer.get().Error()
  * 
  *   cpdef string far_type(self):             # <<<<<<<<<<<<<<
@@ -46461,39 +45479,52 @@ static std::string __pyx_f_9pywrapfst_9FarWriter_far_type(struct __pyx_obj_9pywr
   /* Check if called by wrapper */
   if (unlikely(__pyx_skip_dispatch)) ;
   /* Check if overridden in Python */
-  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_far_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4468, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_9pywrapfst_9FarWriter_13far_type)) {
-      __Pyx_INCREF(__pyx_t_1);
-      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
+  else if (unlikely((Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0) || (Py_TYPE(((PyObject *)__pyx_v_self))->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | Py_TPFLAGS_HEAPTYPE)))) {
+    #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+    static PY_UINT64_T tp_dict_version = 0, obj_dict_version = 0;
+    if (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict && tp_dict_version == __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) && (!Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset || obj_dict_version == __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))))));
+    else {
+      PY_UINT64_T type_dict_guard = (likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict)) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      #endif
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_far_type); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4490, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)(void*)__pyx_pw_9pywrapfst_9FarWriter_13far_type)) {
+        __Pyx_INCREF(__pyx_t_1);
+        __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_3, function);
+          }
         }
+        __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4490, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4490, __pyx_L1_error)
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __pyx_r = __pyx_t_5;
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        goto __pyx_L0;
+      }
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
+      tp_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) ? __PYX_GET_DICT_VERSION(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dict) : 0;
+      obj_dict_version = likely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset) ? __PYX_GET_DICT_VERSION(_PyObject_GetDictPtr(((PyObject *)__pyx_v_self))) : 0;
+      if (unlikely(type_dict_guard != tp_dict_version)) {
+        tp_dict_version = obj_dict_version = 0;
       }
-      if (__pyx_t_4) {
-        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4468, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4468, __pyx_L1_error)
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4468, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_r = __pyx_t_5;
+      #endif
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L0;
+      #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_PYTYPE_LOOKUP
     }
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    #endif
   }
 
-  /* "pywrapfst.pyx":4474
+  /* "pywrapfst.pyx":4496
  *     Returns a string indicating the FAR type.
  *     """
  *     return fst.GetFarTypeString(self._writer.get().Type())             # <<<<<<<<<<<<<<
@@ -46502,12 +45533,12 @@ static std::string __pyx_f_9pywrapfst_9FarWriter_far_type(struct __pyx_obj_9pywr
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "_writer");
-    __PYX_ERR(0, 4474, __pyx_L1_error)
+    __PYX_ERR(0, 4496, __pyx_L1_error)
   }
   __pyx_r = fst::GetFarTypeString(__pyx_v_self->_writer.get()->Type());
   goto __pyx_L0;
 
-  /* "pywrapfst.pyx":4468
+  /* "pywrapfst.pyx":4490
  *     return self._writer.get().Error()
  * 
  *   cpdef string far_type(self):             # <<<<<<<<<<<<<<
@@ -46548,7 +45579,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_12far_type(struct __pyx_obj_9pyw
   PyObject *__pyx_t_1 = NULL;
   __Pyx_RefNannySetupContext("far_type", 0);
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_convert_PyBytes_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarWriter_far_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4468, __pyx_L1_error)
+  __pyx_t_1 = __pyx_convert_PyUnicode_string_to_py_std__in_string(__pyx_f_9pywrapfst_9FarWriter_far_type(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4490, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -46565,7 +45596,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_12far_type(struct __pyx_obj_9pyw
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4477
+/* "pywrapfst.pyx":4499
  * 
  *   # Dictionary-like assignment.
  *   def __setitem__(self, key, _Fst fst):             # <<<<<<<<<<<<<<
@@ -46579,7 +45610,7 @@ static int __pyx_pw_9pywrapfst_9FarWriter_15__setitem__(PyObject *__pyx_v_self,
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__setitem__ (wrapper)", 0);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_fst), __pyx_ptype_9pywrapfst__Fst, 1, "fst", 0))) __PYX_ERR(0, 4477, __pyx_L1_error)
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_fst), __pyx_ptype_9pywrapfst__Fst, 1, "fst", 0))) __PYX_ERR(0, 4499, __pyx_L1_error)
   __pyx_r = __pyx_pf_9pywrapfst_9FarWriter_14__setitem__(((struct __pyx_obj_9pywrapfst_FarWriter *)__pyx_v_self), ((PyObject *)__pyx_v_key), ((struct __pyx_obj_9pywrapfst__Fst *)__pyx_v_fst));
 
   /* function exit code */
@@ -46596,20 +45627,20 @@ static int __pyx_pf_9pywrapfst_9FarWriter_14__setitem__(struct __pyx_obj_9pywrap
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__setitem__", 0);
 
-  /* "pywrapfst.pyx":4478
+  /* "pywrapfst.pyx":4500
  *   # Dictionary-like assignment.
  *   def __setitem__(self, key, _Fst fst):
  *     self.add(key, fst)             # <<<<<<<<<<<<<<
  * 
- * 
+ * # Masks fst_error_fatal in-module.
  */
   if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "add");
-    __PYX_ERR(0, 4478, __pyx_L1_error)
+    __PYX_ERR(0, 4500, __pyx_L1_error)
   }
-  ((struct __pyx_vtabstruct_9pywrapfst_FarWriter *)__pyx_v_self->__pyx_vtab)->add(__pyx_v_self, __pyx_v_key, __pyx_v_fst, 0); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4478, __pyx_L1_error)
+  ((struct __pyx_vtabstruct_9pywrapfst_FarWriter *)__pyx_v_self->__pyx_vtab)->add(__pyx_v_self, __pyx_v_key, __pyx_v_fst, 0); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4500, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":4477
+  /* "pywrapfst.pyx":4499
  * 
  *   # Dictionary-like assignment.
  *   def __setitem__(self, key, _Fst fst):             # <<<<<<<<<<<<<<
@@ -46659,7 +45690,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_16__reduce_cython__(CYTHON_UNUSE
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._writer cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__97, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__58, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -46712,7 +45743,7 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_18__setstate_cython__(CYTHON_UNU
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._writer cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__98, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__59, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -46735,68 +45766,6 @@ static PyObject *__pyx_pf_9pywrapfst_9FarWriter_18__setstate_cython__(CYTHON_UNU
   return __pyx_r;
 }
 
-/* "pywrapfst.pyx":4493
- * 
- * @atexit.register
- * def _reset_fst_error_fatal():             # <<<<<<<<<<<<<<
- *   fst.FLAGS_fst_error_fatal = _fst_error_fatal_old
- * 
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9pywrapfst_59_reset_fst_error_fatal(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyMethodDef __pyx_mdef_9pywrapfst_59_reset_fst_error_fatal = {"_reset_fst_error_fatal", (PyCFunction)__pyx_pw_9pywrapfst_59_reset_fst_error_fatal, METH_NOARGS, 0};
-static PyObject *__pyx_pw_9pywrapfst_59_reset_fst_error_fatal(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_reset_fst_error_fatal (wrapper)", 0);
-  __pyx_r = __pyx_pf_9pywrapfst_58_reset_fst_error_fatal(__pyx_self);
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9pywrapfst_58_reset_fst_error_fatal(CYTHON_UNUSED PyObject *__pyx_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  bool __pyx_t_2;
-  __Pyx_RefNannySetupContext("_reset_fst_error_fatal", 0);
-
-  /* "pywrapfst.pyx":4494
- * @atexit.register
- * def _reset_fst_error_fatal():
- *   fst.FLAGS_fst_error_fatal = _fst_error_fatal_old             # <<<<<<<<<<<<<<
- * 
- */
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_fst_error_fatal_old); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4494, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_2 == ((bool)-1)) && PyErr_Occurred())) __PYX_ERR(0, 4494, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  FLAGS_fst_error_fatal = __pyx_t_2;
-
-  /* "pywrapfst.pyx":4493
- * 
- * @atexit.register
- * def _reset_fst_error_fatal():             # <<<<<<<<<<<<<<
- *   fst.FLAGS_fst_error_fatal = _fst_error_fatal_old
- * 
- */
-
-  /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("pywrapfst._reset_fst_error_fatal", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* "string.from_py":13
  * 
  * @cname("__pyx_convert_string_from_py_std__in_string")
@@ -47202,117 +46171,6 @@ static std::vector<__pyx_t_10basictypes_int64>  __pyx_convert_vector_from_py___p
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
-
-static std::vector<std::string>  __pyx_convert_vector_from_py_std_3a__3a_string(PyObject *__pyx_v_o) {
-  std::vector<std::string>  __pyx_v_v;
-  PyObject *__pyx_v_item = NULL;
-  std::vector<std::string>  __pyx_r;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  Py_ssize_t __pyx_t_2;
-  PyObject *(*__pyx_t_3)(PyObject *);
-  PyObject *__pyx_t_4 = NULL;
-  std::string __pyx_t_5;
-  __Pyx_RefNannySetupContext("__pyx_convert_vector_from_py_std_3a__3a_string", 0);
-
-  /* "vector.from_py":47
- * cdef vector[X] __pyx_convert_vector_from_py_std_3a__3a_string(object o) except *:
- *     cdef vector[X] v
- *     for item in o:             # <<<<<<<<<<<<<<
- *         v.push_back(<X>item)
- *     return v
- */
-  if (likely(PyList_CheckExact(__pyx_v_o)) || PyTuple_CheckExact(__pyx_v_o)) {
-    __pyx_t_1 = __pyx_v_o; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
-    __pyx_t_3 = NULL;
-  } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_o); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 47, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 47, __pyx_L1_error)
-  }
-  for (;;) {
-    if (likely(!__pyx_t_3)) {
-      if (likely(PyList_CheckExact(__pyx_t_1))) {
-        if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) __PYX_ERR(1, 47, __pyx_L1_error)
-        #else
-        __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 47, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        #endif
-      } else {
-        if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) __PYX_ERR(1, 47, __pyx_L1_error)
-        #else
-        __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 47, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        #endif
-      }
-    } else {
-      __pyx_t_4 = __pyx_t_3(__pyx_t_1);
-      if (unlikely(!__pyx_t_4)) {
-        PyObject* exc_type = PyErr_Occurred();
-        if (exc_type) {
-          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(1, 47, __pyx_L1_error)
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_4);
-    }
-    __Pyx_XDECREF_SET(__pyx_v_item, __pyx_t_4);
-    __pyx_t_4 = 0;
-
-    /* "vector.from_py":48
- *     cdef vector[X] v
- *     for item in o:
- *         v.push_back(<X>item)             # <<<<<<<<<<<<<<
- *     return v
- * 
- */
-    __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_v_item); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 48, __pyx_L1_error)
-    __pyx_v_v.push_back(((std::string)__pyx_t_5));
-
-    /* "vector.from_py":47
- * cdef vector[X] __pyx_convert_vector_from_py_std_3a__3a_string(object o) except *:
- *     cdef vector[X] v
- *     for item in o:             # <<<<<<<<<<<<<<
- *         v.push_back(<X>item)
- *     return v
- */
-  }
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-  /* "vector.from_py":49
- *     for item in o:
- *         v.push_back(<X>item)
- *     return v             # <<<<<<<<<<<<<<
- * 
- * 
- */
-  __pyx_r = __pyx_v_v;
-  goto __pyx_L0;
-
-  /* "vector.from_py":45
- * 
- * @cname("__pyx_convert_vector_from_py_std_3a__3a_string")
- * cdef vector[X] __pyx_convert_vector_from_py_std_3a__3a_string(object o) except *:             # <<<<<<<<<<<<<<
- *     cdef vector[X] v
- *     for item in o:
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vector.from_py.__pyx_convert_vector_from_py_std_3a__3a_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_pretend_to_initialize(&__pyx_r);
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_item);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
 static struct __pyx_vtabstruct_9pywrapfst_Weight __pyx_vtable_9pywrapfst_Weight;
 
 static PyObject *__pyx_tp_new_9pywrapfst_Weight(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
@@ -47512,19 +46370,19 @@ static void __pyx_tp_dealloc_9pywrapfst__SymbolTable(PyObject *o) {
 }
 
 static PyMethodDef __pyx_methods_9pywrapfst__SymbolTable[] = {
-  {"available_key", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_5available_key, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_4available_key},
-  {"checksum", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_7checksum, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_6checksum},
-  {"copy", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_9copy, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_8copy},
-  {"find", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_11find, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_10find},
-  {"get_nth_key", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_13get_nth_key, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_12get_nth_key},
-  {"labeled_checksum", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_15labeled_checksum, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_14labeled_checksum},
-  {"member", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_17member, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_16member},
-  {"name", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_21name, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_20name},
-  {"num_symbols", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_23num_symbols, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_22num_symbols},
-  {"write", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_25write, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_24write},
-  {"write_text", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_27write_text, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_26write_text},
-  {"__reduce_cython__", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_29__reduce_cython__, METH_NOARGS, 0},
-  {"__setstate_cython__", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_31__setstate_cython__, METH_O, 0},
+  {"__reduce__", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_5__reduce__, METH_NOARGS, 0},
+  {"available_key", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_7available_key, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_6available_key},
+  {"checksum", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_9checksum, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_8checksum},
+  {"copy", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_11copy, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_10copy},
+  {"find", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_13find, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_12find},
+  {"get_nth_key", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_15get_nth_key, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_14get_nth_key},
+  {"labeled_checksum", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_17labeled_checksum, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_16labeled_checksum},
+  {"member", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_19member, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_18member},
+  {"name", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_23name, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_22name},
+  {"num_symbols", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_25num_symbols, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_24num_symbols},
+  {"write", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_27write, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_26write},
+  {"write_text", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_29write_text, METH_O, __pyx_doc_9pywrapfst_12_SymbolTable_28write_text},
+  {"write_to_string", (PyCFunction)__pyx_pw_9pywrapfst_12_SymbolTable_31write_to_string, METH_NOARGS, __pyx_doc_9pywrapfst_12_SymbolTable_30write_to_string},
   {0, 0, 0, 0}
 };
 
@@ -47536,7 +46394,7 @@ static PySequenceMethods __pyx_tp_as_sequence__SymbolTable = {
   0, /*sq_slice*/
   0, /*sq_ass_item*/
   0, /*sq_ass_slice*/
-  __pyx_pw_9pywrapfst_12_SymbolTable_19__contains__, /*sq_contains*/
+  __pyx_pw_9pywrapfst_12_SymbolTable_21__contains__, /*sq_contains*/
   0, /*sq_inplace_concat*/
   0, /*sq_inplace_repeat*/
 };
@@ -47622,8 +46480,6 @@ static void __pyx_tp_dealloc_9pywrapfst__EncodeMapperSymbolTable(PyObject *o) {
 }
 
 static PyMethodDef __pyx_methods_9pywrapfst__EncodeMapperSymbolTable[] = {
-  {"__reduce_cython__", (PyCFunction)__pyx_pw_9pywrapfst_24_EncodeMapperSymbolTable_3__reduce_cython__, METH_NOARGS, 0},
-  {"__setstate_cython__", (PyCFunction)__pyx_pw_9pywrapfst_24_EncodeMapperSymbolTable_5__setstate_cython__, METH_O, 0},
   {0, 0, 0, 0}
 };
 
@@ -47716,8 +46572,6 @@ static void __pyx_tp_dealloc_9pywrapfst__FstSymbolTable(PyObject *o) {
 }
 
 static PyMethodDef __pyx_methods_9pywrapfst__FstSymbolTable[] = {
-  {"__reduce_cython__", (PyCFunction)__pyx_pw_9pywrapfst_15_FstSymbolTable_3__reduce_cython__, METH_NOARGS, 0},
-  {"__setstate_cython__", (PyCFunction)__pyx_pw_9pywrapfst_15_FstSymbolTable_5__setstate_cython__, METH_O, 0},
   {0, 0, 0, 0}
 };
 
@@ -47798,11 +46652,9 @@ static PyObject *__pyx_tp_new_9pywrapfst__MutableSymbolTable(PyTypeObject *t, Py
 }
 
 static PyMethodDef __pyx_methods_9pywrapfst__MutableSymbolTable[] = {
-  {"add_symbol", (PyCFunction)__pyx_pw_9pywrapfst_19_MutableSymbolTable_1add_symbol, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_19_MutableSymbolTable_add_symbol},
+  {"add_symbol", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_19_MutableSymbolTable_1add_symbol, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_19_MutableSymbolTable_add_symbol},
   {"add_table", (PyCFunction)__pyx_pw_9pywrapfst_19_MutableSymbolTable_3add_table, METH_O, __pyx_doc_9pywrapfst_19_MutableSymbolTable_2add_table},
   {"set_name", (PyCFunction)__pyx_pw_9pywrapfst_19_MutableSymbolTable_5set_name, METH_O, 0},
-  {"__reduce_cython__", (PyCFunction)__pyx_pw_9pywrapfst_19_MutableSymbolTable_7__reduce_cython__, METH_NOARGS, 0},
-  {"__setstate_cython__", (PyCFunction)__pyx_pw_9pywrapfst_19_MutableSymbolTable_9__setstate_cython__, METH_O, 0},
   {0, 0, 0, 0}
 };
 
@@ -47895,8 +46747,6 @@ static void __pyx_tp_dealloc_9pywrapfst__MutableFstSymbolTable(PyObject *o) {
 }
 
 static PyMethodDef __pyx_methods_9pywrapfst__MutableFstSymbolTable[] = {
-  {"__reduce_cython__", (PyCFunction)__pyx_pw_9pywrapfst_22_MutableFstSymbolTable_3__reduce_cython__, METH_NOARGS, 0},
-  {"__setstate_cython__", (PyCFunction)__pyx_pw_9pywrapfst_22_MutableFstSymbolTable_5__setstate_cython__, METH_O, 0},
   {0, 0, 0, 0}
 };
 
@@ -47990,10 +46840,8 @@ static void __pyx_tp_dealloc_9pywrapfst_SymbolTable(PyObject *o) {
 
 static PyMethodDef __pyx_methods_9pywrapfst_SymbolTable[] = {
   {"read", (PyCFunction)__pyx_pw_9pywrapfst_11SymbolTable_5read, METH_O, __pyx_doc_9pywrapfst_11SymbolTable_4read},
-  {"read_text", (PyCFunction)__pyx_pw_9pywrapfst_11SymbolTable_7read_text, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11SymbolTable_6read_text},
-  {"read_fst", (PyCFunction)__pyx_pw_9pywrapfst_11SymbolTable_9read_fst, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11SymbolTable_8read_fst},
-  {"__reduce_cython__", (PyCFunction)__pyx_pw_9pywrapfst_11SymbolTable_11__reduce_cython__, METH_NOARGS, 0},
-  {"__setstate_cython__", (PyCFunction)__pyx_pw_9pywrapfst_11SymbolTable_13__setstate_cython__, METH_O, 0},
+  {"read_text", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11SymbolTable_7read_text, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11SymbolTable_6read_text},
+  {"read_fst", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11SymbolTable_9read_fst, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11SymbolTable_8read_fst},
   {0, 0, 0, 0}
 };
 
@@ -48088,8 +46936,10 @@ static void __pyx_tp_dealloc_9pywrapfst_SymbolTableIterator(PyObject *o) {
   (*Py_TYPE(o)->tp_free)(o);
 }
 
+static PyObject *__pyx_specialmethod___pyx_pw_9pywrapfst_19SymbolTableIterator_7__next__(PyObject *self, CYTHON_UNUSED PyObject *arg) {return __pyx_pw_9pywrapfst_19SymbolTableIterator_7__next__(self);}
+
 static PyMethodDef __pyx_methods_9pywrapfst_SymbolTableIterator[] = {
-  {"__next__", (PyCFunction)__pyx_pw_9pywrapfst_19SymbolTableIterator_7__next__, METH_NOARGS|METH_COEXIST, 0},
+  {"__next__", (PyCFunction)__pyx_specialmethod___pyx_pw_9pywrapfst_19SymbolTableIterator_7__next__, METH_NOARGS|METH_COEXIST, 0},
   {"done", (PyCFunction)__pyx_pw_9pywrapfst_19SymbolTableIterator_9done, METH_NOARGS, __pyx_doc_9pywrapfst_19SymbolTableIterator_8done},
   {"next", (PyCFunction)__pyx_pw_9pywrapfst_19SymbolTableIterator_11next, METH_NOARGS, __pyx_doc_9pywrapfst_19SymbolTableIterator_10next},
   {"reset", (PyCFunction)__pyx_pw_9pywrapfst_19SymbolTableIterator_13reset, METH_NOARGS, __pyx_doc_9pywrapfst_19SymbolTableIterator_12reset},
@@ -48286,11 +47136,11 @@ static void __pyx_tp_dealloc_9pywrapfst__Fst(PyObject *o) {
 
 static PyMethodDef __pyx_methods_9pywrapfst__Fst[] = {
   {"_repr_svg_", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_1_repr_svg_, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst__repr_svg_},
-  {"__reduce__", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_9__reduce__, METH_NOARGS, 0},
+  {"__reduce__", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_5__reduce__, METH_NOARGS, 0},
   {"arc_type", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_11arc_type, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst_10arc_type},
   {"arcs", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_13arcs, METH_O, __pyx_doc_9pywrapfst_4_Fst_12arcs},
   {"copy", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_15copy, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst_14copy},
-  {"draw", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_17draw, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_4_Fst_16draw},
+  {"draw", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_4_Fst_17draw, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_4_Fst_16draw},
   {"final", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_19final, METH_O, __pyx_doc_9pywrapfst_4_Fst_18final},
   {"fst_type", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_21fst_type, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst_20fst_type},
   {"input_symbols", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_23input_symbols, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst_22input_symbols},
@@ -48298,10 +47148,10 @@ static PyMethodDef __pyx_methods_9pywrapfst__Fst[] = {
   {"num_input_epsilons", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_27num_input_epsilons, METH_O, __pyx_doc_9pywrapfst_4_Fst_26num_input_epsilons},
   {"num_output_epsilons", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_29num_output_epsilons, METH_O, __pyx_doc_9pywrapfst_4_Fst_28num_output_epsilons},
   {"output_symbols", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_31output_symbols, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst_30output_symbols},
-  {"properties", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_33properties, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_4_Fst_32properties},
+  {"properties", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_4_Fst_33properties, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_4_Fst_32properties},
   {"start", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_35start, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst_34start},
   {"states", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_37states, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst_36states},
-  {"text", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_39text, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_4_Fst_38text},
+  {"text", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_4_Fst_39text, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_4_Fst_38text},
   {"verify", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_41verify, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst_40verify},
   {"weight_type", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_43weight_type, METH_NOARGS, __pyx_doc_9pywrapfst_4_Fst_42weight_type},
   {"write", (PyCFunction)__pyx_pw_9pywrapfst_4_Fst_45write, METH_O, __pyx_doc_9pywrapfst_4_Fst_44write},
@@ -48324,13 +47174,13 @@ static PyTypeObject __pyx_type_9pywrapfst__Fst = {
   #if PY_MAJOR_VERSION >= 3
   0, /*tp_as_async*/
   #endif
-  __pyx_pw_9pywrapfst_4_Fst_3__repr__, /*tp_repr*/
+  __pyx_pw_9pywrapfst_4_Fst_7__repr__, /*tp_repr*/
   0, /*tp_as_number*/
   0, /*tp_as_sequence*/
   0, /*tp_as_mapping*/
   0, /*tp_hash*/
   0, /*tp_call*/
-  __pyx_pw_9pywrapfst_4_Fst_7__str__, /*tp_str*/
+  __pyx_pw_9pywrapfst_4_Fst_9__str__, /*tp_str*/
   0, /*tp_getattro*/
   0, /*tp_setattro*/
   0, /*tp_as_buffer*/
@@ -48350,7 +47200,7 @@ static PyTypeObject __pyx_type_9pywrapfst__Fst = {
   0, /*tp_descr_get*/
   0, /*tp_descr_set*/
   0, /*tp_dictoffset*/
-  __pyx_pw_9pywrapfst_4_Fst_5__init__, /*tp_init*/
+  __pyx_pw_9pywrapfst_4_Fst_3__init__, /*tp_init*/
   0, /*tp_alloc*/
   __pyx_tp_new_9pywrapfst__Fst, /*tp_new*/
   0, /*tp_free*/
@@ -48390,35 +47240,35 @@ static void __pyx_tp_dealloc_9pywrapfst__MutableFst(PyObject *o) {
 }
 
 static PyMethodDef __pyx_methods_9pywrapfst__MutableFst[] = {
-  {"add_arc", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_1add_arc, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_add_arc},
+  {"add_arc", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_1add_arc, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_add_arc},
   {"add_state", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_3add_state, METH_NOARGS, __pyx_doc_9pywrapfst_11_MutableFst_2add_state},
-  {"arcsort", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_5arcsort, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_4arcsort},
-  {"closure", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_7closure, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_6closure},
+  {"arcsort", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_5arcsort, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_4arcsort},
+  {"closure", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_7closure, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_6closure},
   {"concat", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_9concat, METH_O, __pyx_doc_9pywrapfst_11_MutableFst_8concat},
   {"connect", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_11connect, METH_NOARGS, __pyx_doc_9pywrapfst_11_MutableFst_10connect},
   {"decode", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_13decode, METH_O, __pyx_doc_9pywrapfst_11_MutableFst_12decode},
-  {"delete_arcs", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_15delete_arcs, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_14delete_arcs},
-  {"delete_states", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_17delete_states, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_16delete_states},
+  {"delete_arcs", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_15delete_arcs, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_14delete_arcs},
+  {"delete_states", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_17delete_states, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_16delete_states},
   {"encode", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_19encode, METH_O, __pyx_doc_9pywrapfst_11_MutableFst_18encode},
   {"invert", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_21invert, METH_NOARGS, __pyx_doc_9pywrapfst_11_MutableFst_20invert},
-  {"minimize", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_23minimize, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_22minimize},
+  {"minimize", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_23minimize, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_22minimize},
   {"mutable_arcs", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_25mutable_arcs, METH_O, __pyx_doc_9pywrapfst_11_MutableFst_24mutable_arcs},
   {"mutable_input_symbols", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_27mutable_input_symbols, METH_NOARGS, __pyx_doc_9pywrapfst_11_MutableFst_26mutable_input_symbols},
   {"mutable_output_symbols", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_29mutable_output_symbols, METH_NOARGS, __pyx_doc_9pywrapfst_11_MutableFst_28mutable_output_symbols},
   {"num_states", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_31num_states, METH_NOARGS, __pyx_doc_9pywrapfst_11_MutableFst_30num_states},
-  {"project", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_33project, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_32project},
-  {"prune", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_35prune, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_34prune},
-  {"push", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_37push, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_36push},
-  {"relabel_pairs", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_39relabel_pairs, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_38relabel_pairs},
-  {"relabel_tables", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_40relabel_tables},
-  {"reserve_arcs", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_43reserve_arcs, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_42reserve_arcs},
+  {"project", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_33project, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_32project},
+  {"prune", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_35prune, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_34prune},
+  {"push", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_37push, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_36push},
+  {"relabel_pairs", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_39relabel_pairs, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_38relabel_pairs},
+  {"relabel_tables", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_41relabel_tables, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_40relabel_tables},
+  {"reserve_arcs", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_43reserve_arcs, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_42reserve_arcs},
   {"reserve_states", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_45reserve_states, METH_O, __pyx_doc_9pywrapfst_11_MutableFst_44reserve_states},
-  {"reweight", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_47reweight, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_46reweight},
-  {"rmepsilon", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_49rmepsilon, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_48rmepsilon},
-  {"set_final", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_51set_final, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_50set_final},
+  {"reweight", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_47reweight, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_46reweight},
+  {"rmepsilon", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_49rmepsilon, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_48rmepsilon},
+  {"set_final", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_51set_final, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_50set_final},
   {"set_input_symbols", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_53set_input_symbols, METH_O, __pyx_doc_9pywrapfst_11_MutableFst_52set_input_symbols},
   {"set_output_symbols", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_55set_output_symbols, METH_O, __pyx_doc_9pywrapfst_11_MutableFst_54set_output_symbols},
-  {"set_properties", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_57set_properties, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_56set_properties},
+  {"set_properties", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11_MutableFst_57set_properties, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11_MutableFst_56set_properties},
   {"set_start", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_59set_start, METH_O, __pyx_doc_9pywrapfst_11_MutableFst_58set_start},
   {"topsort", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_61topsort, METH_NOARGS, __pyx_doc_9pywrapfst_11_MutableFst_60topsort},
   {"union", (PyCFunction)__pyx_pw_9pywrapfst_11_MutableFst_63union, METH_O, __pyx_doc_9pywrapfst_11_MutableFst_62union},
@@ -48441,7 +47291,7 @@ static PyTypeObject __pyx_type_9pywrapfst__MutableFst = {
   0, /*tp_as_async*/
   #endif
   #if CYTHON_COMPILING_IN_PYPY
-  __pyx_pw_9pywrapfst_4_Fst_3__repr__, /*tp_repr*/
+  __pyx_pw_9pywrapfst_4_Fst_7__repr__, /*tp_repr*/
   #else
   0, /*tp_repr*/
   #endif
@@ -48451,7 +47301,7 @@ static PyTypeObject __pyx_type_9pywrapfst__MutableFst = {
   0, /*tp_hash*/
   0, /*tp_call*/
   #if CYTHON_COMPILING_IN_PYPY
-  __pyx_pw_9pywrapfst_4_Fst_7__str__, /*tp_str*/
+  __pyx_pw_9pywrapfst_4_Fst_9__str__, /*tp_str*/
   #else
   0, /*tp_str*/
   #endif
@@ -48475,7 +47325,7 @@ static PyTypeObject __pyx_type_9pywrapfst__MutableFst = {
   0, /*tp_descr_set*/
   0, /*tp_dictoffset*/
   #if CYTHON_COMPILING_IN_PYPY
-  __pyx_pw_9pywrapfst_4_Fst_5__init__, /*tp_init*/
+  __pyx_pw_9pywrapfst_4_Fst_3__init__, /*tp_init*/
   #else
   0, /*tp_init*/
   #endif
@@ -48680,15 +47530,17 @@ static void __pyx_tp_dealloc_9pywrapfst_ArcIterator(PyObject *o) {
   (*Py_TYPE(o)->tp_free)(o);
 }
 
+static PyObject *__pyx_specialmethod___pyx_pw_9pywrapfst_11ArcIterator_7__next__(PyObject *self, CYTHON_UNUSED PyObject *arg) {return __pyx_pw_9pywrapfst_11ArcIterator_7__next__(self);}
+
 static PyMethodDef __pyx_methods_9pywrapfst_ArcIterator[] = {
-  {"__next__", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_7__next__, METH_NOARGS|METH_COEXIST, 0},
+  {"__next__", (PyCFunction)__pyx_specialmethod___pyx_pw_9pywrapfst_11ArcIterator_7__next__, METH_NOARGS|METH_COEXIST, 0},
   {"done", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_9done, METH_NOARGS, __pyx_doc_9pywrapfst_11ArcIterator_8done},
   {"flags", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_11flags, METH_NOARGS, __pyx_doc_9pywrapfst_11ArcIterator_10flags},
   {"next", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_13next, METH_NOARGS, __pyx_doc_9pywrapfst_11ArcIterator_12next},
   {"position", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_15position, METH_NOARGS, __pyx_doc_9pywrapfst_11ArcIterator_14position},
   {"reset", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_17reset, METH_NOARGS, __pyx_doc_9pywrapfst_11ArcIterator_16reset},
   {"seek", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_19seek, METH_O, __pyx_doc_9pywrapfst_11ArcIterator_18seek},
-  {"set_flags", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_21set_flags, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11ArcIterator_20set_flags},
+  {"set_flags", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_11ArcIterator_21set_flags, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_11ArcIterator_20set_flags},
   {"value", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_23value, METH_NOARGS, __pyx_doc_9pywrapfst_11ArcIterator_22value},
   {"__reduce_cython__", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_25__reduce_cython__, METH_NOARGS, 0},
   {"__setstate_cython__", (PyCFunction)__pyx_pw_9pywrapfst_11ArcIterator_27__setstate_cython__, METH_O, 0},
@@ -48789,7 +47641,7 @@ static PyMethodDef __pyx_methods_9pywrapfst_MutableArcIterator[] = {
   {"position", (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_11position, METH_NOARGS, __pyx_doc_9pywrapfst_18MutableArcIterator_10position},
   {"reset", (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_13reset, METH_NOARGS, __pyx_doc_9pywrapfst_18MutableArcIterator_12reset},
   {"seek", (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_15seek, METH_O, __pyx_doc_9pywrapfst_18MutableArcIterator_14seek},
-  {"set_flags", (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_17set_flags, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_18MutableArcIterator_16set_flags},
+  {"set_flags", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_18MutableArcIterator_17set_flags, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_18MutableArcIterator_16set_flags},
   {"set_value", (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_19set_value, METH_O, __pyx_doc_9pywrapfst_18MutableArcIterator_18set_value},
   {"value", (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_21value, METH_NOARGS, __pyx_doc_9pywrapfst_18MutableArcIterator_20value},
   {"__reduce_cython__", (PyCFunction)__pyx_pw_9pywrapfst_18MutableArcIterator_23__reduce_cython__, METH_NOARGS, 0},
@@ -48884,8 +47736,10 @@ static void __pyx_tp_dealloc_9pywrapfst_StateIterator(PyObject *o) {
   (*Py_TYPE(o)->tp_free)(o);
 }
 
+static PyObject *__pyx_specialmethod___pyx_pw_9pywrapfst_13StateIterator_7__next__(PyObject *self, CYTHON_UNUSED PyObject *arg) {return __pyx_pw_9pywrapfst_13StateIterator_7__next__(self);}
+
 static PyMethodDef __pyx_methods_9pywrapfst_StateIterator[] = {
-  {"__next__", (PyCFunction)__pyx_pw_9pywrapfst_13StateIterator_7__next__, METH_NOARGS|METH_COEXIST, 0},
+  {"__next__", (PyCFunction)__pyx_specialmethod___pyx_pw_9pywrapfst_13StateIterator_7__next__, METH_NOARGS|METH_COEXIST, 0},
   {"done", (PyCFunction)__pyx_pw_9pywrapfst_13StateIterator_9done, METH_NOARGS, __pyx_doc_9pywrapfst_13StateIterator_8done},
   {"next", (PyCFunction)__pyx_pw_9pywrapfst_13StateIterator_11next, METH_NOARGS, __pyx_doc_9pywrapfst_13StateIterator_10next},
   {"reset", (PyCFunction)__pyx_pw_9pywrapfst_13StateIterator_13reset, METH_NOARGS, __pyx_doc_9pywrapfst_13StateIterator_12reset},
@@ -49022,7 +47876,7 @@ static PyTypeObject __pyx_type_9pywrapfst_Compiler = {
   0, /*tp_setattro*/
   0, /*tp_as_buffer*/
   Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
-  "\n  Compiler(fst_type=\"vector\", arc_type=\"standard\", isymbols=None,\n           osymbols=None, ssymbols=None, acceptor=False, keep_isymbols=False,\n           keep_osymbols=False, keep_state_numbering=False,\n           allow_negative_labels=False)\n\n  Class used to compile FSTs from strings.\n\n  This class is used to compile FSTs specified using the AT&T FSM library\n  format described here:\n\n  http://web.eecs.umich.edu/~radev/NLP-fall2015/resources/fsm_archive/fsm.5.html\n\n  This is the same format used by the `fstcompile` executable.\n\n  Compiler options (symbol tables, etc.) are set at construction time.\n\n      compiler = fst.Compiler(isymbols=ascii_syms, osymbols=ascii_syms)\n\n  Once constructed, Compiler instances behave like a file handle opened for\n  writing:\n\n      # /ba+/\n      print >> compiler, \"0 1 50 50\"\n      print >> compiler, \"1 2 49 49\"\n      print >> compiler, \"2 2 49 49\"\n      print >> compiler, \"2\"\n\n  The `compile` method returns an actual FST instance:\n\n      sheep_machine = compiler.compile()\n\n  Compilation flushes the internal buffer, so the compiler instance can be\n  reused to compile new machines with the same symbol tables (etc.)\n\n  Args:\n    fst_type: A string indicating the container type for the compiled FST.\n    arc_type: A string indicating the arc type for the compiled FST.\n    isymbols: An optional SymbolTable used to label input symbols.\n    osymbols: An optional SymbolTable used to label output symbols.\n    ssymbols: An optional SymbolTable used to label states.\n    acceptor: Should the FST be rendered in acceptor format if possible?\n    keep_isymbols: Should the input symbol table be stored in the FST?\n    keep_osymbols: Should the output symbol table be stored in the FST?\n    keep_state_numbering: Should the state numbering be preserved?\n    allow_negative_labels: Should negative labels be allowed? (Not\n        recommended; may cause conflicts).\n  ", /*tp_doc*/
+  "\n  Compiler(fst_type=\"vector\", arc_type=\"standard\", isymbols=None,\n           osymbols=None, ssymbols=None, acceptor=False, keep_isymbols=False,\n           keep_osymbols=False, keep_state_numbering=False,\n           allow_negative_labels=False)\n\n  Class used to compile FSTs from strings.\n\n  This class is used to compile FSTs specified using the AT&T FSM library\n  format described here:\n\n  http://web.eecs.umich.edu/~radev/NLP-fall2015/resources/fsm_archive/fsm.5.html\n\n  This is the same format used by the `fstcompile` executable.\n\n  Compiler options (symbol tables, etc.) are set at construction time.\n\n      compiler = fst.Compiler(isymbols=ascii_syms, osymbols=ascii_syms)\n\n  Once constructed, Compiler instances behave like a file handle opened for\n  writing:\n\n      # /ba+/\n      compiler.write(\"0 1 50 50\")\n      compiler.write(\"1 2 49 49\")\n      compiler.write(\"2 2 49 49\")\n      compiler.write(\"2\")\n\n  The `compile` method returns an actual FST instance:\n\n      sheep_machine = compiler.compile()\n\n  Compilation flushes the internal buffer, so the compiler instance can be\n  reused to compile new machines with the same symbol tables (etc.)\n\n  Args:\n    fst_type: A string indicating the container type for the compiled FST.\n    arc_type: A string indicating the arc type for the compiled FST.\n    isymbols: An optional SymbolTable used to label input symbols.\n    osymbols: An optional SymbolTable used to label output symbols.\n    ssymbols: An optional SymbolTable used to label states.\n    acceptor: Should the FST be rendered in acceptor format if possible?\n    keep_isymbols: Should the input symbol table be stored in the FST?\n    keep_osymbols: Should the output symbol table be stored in the FST?\n    keep_state_numbering: Should the state numbering be preserved?\n    allow_negative_labels: Should negative labels be allowed? (Not\n        recommended; may cause conflicts).\n  ", /*tp_doc*/
   0, /*tp_traverse*/
   0, /*tp_clear*/
   0, /*tp_richcompare*/
@@ -49089,7 +47943,7 @@ static PyObject *__pyx_sq_item_9pywrapfst_FarReader(PyObject *o, Py_ssize_t i) {
 }
 
 static PyMethodDef __pyx_methods_9pywrapfst_FarReader[] = {
-  {"open", (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_5open, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_9FarReader_4open},
+  {"open", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_9FarReader_5open, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_9FarReader_4open},
   {"arc_type", (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_7arc_type, METH_NOARGS, __pyx_doc_9pywrapfst_9FarReader_6arc_type},
   {"done", (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_9done, METH_NOARGS, __pyx_doc_9pywrapfst_9FarReader_8done},
   {"error", (PyCFunction)__pyx_pw_9pywrapfst_9FarReader_11error, METH_NOARGS, __pyx_doc_9pywrapfst_9FarReader_10error},
@@ -49220,8 +48074,8 @@ static int __pyx_mp_ass_subscript_9pywrapfst_FarWriter(PyObject *o, PyObject *i,
 }
 
 static PyMethodDef __pyx_methods_9pywrapfst_FarWriter[] = {
-  {"create", (PyCFunction)__pyx_pw_9pywrapfst_9FarWriter_5create, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_9FarWriter_4create},
-  {"add", (PyCFunction)__pyx_pw_9pywrapfst_9FarWriter_7add, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_9FarWriter_6add},
+  {"create", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_9FarWriter_5create, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_9FarWriter_4create},
+  {"add", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_9FarWriter_7add, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_9FarWriter_6add},
   {"arc_type", (PyCFunction)__pyx_pw_9pywrapfst_9FarWriter_9arc_type, METH_NOARGS, __pyx_doc_9pywrapfst_9FarWriter_8arc_type},
   {"error", (PyCFunction)__pyx_pw_9pywrapfst_9FarWriter_11error, METH_NOARGS, __pyx_doc_9pywrapfst_9FarWriter_10error},
   {"far_type", (PyCFunction)__pyx_pw_9pywrapfst_9FarWriter_13far_type, METH_NOARGS, __pyx_doc_9pywrapfst_9FarWriter_12far_type},
@@ -49295,30 +48149,31 @@ static PyTypeObject __pyx_type_9pywrapfst_FarWriter = {
 };
 
 static PyMethodDef __pyx_methods[] = {
-  {"compact_symbol_table", (PyCFunction)__pyx_pw_9pywrapfst_9compact_symbol_table, METH_O, __pyx_doc_9pywrapfst_8compact_symbol_table},
-  {"merge_symbol_table", (PyCFunction)__pyx_pw_9pywrapfst_11merge_symbol_table, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_10merge_symbol_table},
-  {"_read", (PyCFunction)__pyx_pw_9pywrapfst_13_read, METH_O, 0},
-  {"_read_from_string", (PyCFunction)__pyx_pw_9pywrapfst_15_read_from_string, METH_O, 0},
-  {"arcmap", (PyCFunction)__pyx_pw_9pywrapfst_17arcmap, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_16arcmap},
-  {"compose", (PyCFunction)__pyx_pw_9pywrapfst_19compose, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_18compose},
-  {"convert", (PyCFunction)__pyx_pw_9pywrapfst_21convert, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_20convert},
-  {"determinize", (PyCFunction)__pyx_pw_9pywrapfst_23determinize, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_22determinize},
-  {"difference", (PyCFunction)__pyx_pw_9pywrapfst_25difference, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_24difference},
-  {"disambiguate", (PyCFunction)__pyx_pw_9pywrapfst_27disambiguate, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_26disambiguate},
-  {"epsnormalize", (PyCFunction)__pyx_pw_9pywrapfst_29epsnormalize, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_28epsnormalize},
-  {"equal", (PyCFunction)__pyx_pw_9pywrapfst_31equal, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_30equal},
-  {"equivalent", (PyCFunction)__pyx_pw_9pywrapfst_33equivalent, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_32equivalent},
-  {"intersect", (PyCFunction)__pyx_pw_9pywrapfst_35intersect, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_34intersect},
-  {"isomorphic", (PyCFunction)__pyx_pw_9pywrapfst_37isomorphic, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_36isomorphic},
-  {"prune", (PyCFunction)__pyx_pw_9pywrapfst_39prune, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_38prune},
-  {"push", (PyCFunction)__pyx_pw_9pywrapfst_41push, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_40push},
-  {"randequivalent", (PyCFunction)__pyx_pw_9pywrapfst_43randequivalent, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_42randequivalent},
-  {"randgen", (PyCFunction)__pyx_pw_9pywrapfst_45randgen, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_44randgen},
-  {"replace", (PyCFunction)__pyx_pw_9pywrapfst_47replace, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_46replace},
-  {"reverse", (PyCFunction)__pyx_pw_9pywrapfst_49reverse, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_48reverse},
-  {"shortestpath", (PyCFunction)__pyx_pw_9pywrapfst_53shortestpath, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_52shortestpath},
-  {"statemap", (PyCFunction)__pyx_pw_9pywrapfst_55statemap, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_54statemap},
-  {"synchronize", (PyCFunction)__pyx_pw_9pywrapfst_57synchronize, METH_O, __pyx_doc_9pywrapfst_56synchronize},
+  {"_read_SymbolTable_from_string", (PyCFunction)__pyx_pw_9pywrapfst_9_read_SymbolTable_from_string, METH_O, 0},
+  {"compact_symbol_table", (PyCFunction)__pyx_pw_9pywrapfst_11compact_symbol_table, METH_O, __pyx_doc_9pywrapfst_10compact_symbol_table},
+  {"merge_symbol_table", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_13merge_symbol_table, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_12merge_symbol_table},
+  {"_read", (PyCFunction)__pyx_pw_9pywrapfst_15_read, METH_O, 0},
+  {"_read_Fst_from_string", (PyCFunction)__pyx_pw_9pywrapfst_17_read_Fst_from_string, METH_O, 0},
+  {"arcmap", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_19arcmap, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_18arcmap},
+  {"compose", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_21compose, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_20compose},
+  {"convert", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_23convert, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_22convert},
+  {"determinize", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_25determinize, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_24determinize},
+  {"difference", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_27difference, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_26difference},
+  {"disambiguate", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_29disambiguate, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_28disambiguate},
+  {"epsnormalize", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_31epsnormalize, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_30epsnormalize},
+  {"equal", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_33equal, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_32equal},
+  {"equivalent", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_35equivalent, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_34equivalent},
+  {"intersect", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_37intersect, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_36intersect},
+  {"isomorphic", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_39isomorphic, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_38isomorphic},
+  {"prune", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_41prune, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_40prune},
+  {"push", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_43push, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_42push},
+  {"randequivalent", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_45randequivalent, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_44randequivalent},
+  {"randgen", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_47randgen, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_46randgen},
+  {"replace", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_49replace, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_48replace},
+  {"reverse", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_51reverse, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_50reverse},
+  {"shortestpath", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_55shortestpath, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_54shortestpath},
+  {"statemap", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9pywrapfst_57statemap, METH_VARARGS|METH_KEYWORDS, __pyx_doc_9pywrapfst_56statemap},
+  {"synchronize", (PyCFunction)__pyx_pw_9pywrapfst_59synchronize, METH_O, __pyx_doc_9pywrapfst_58synchronize},
   {0, 0, 0, 0}
 };
 
@@ -49353,6 +48208,15 @@ static struct PyModuleDef __pyx_moduledef = {
     NULL /* m_free */
 };
 #endif
+#ifndef CYTHON_SMALL_CODE
+#if defined(__clang__)
+    #define CYTHON_SMALL_CODE
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+    #define CYTHON_SMALL_CODE __attribute__((cold))
+#else
+    #define CYTHON_SMALL_CODE
+#endif
+#endif
 
 static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_ACCEPTOR, __pyx_k_ACCEPTOR, sizeof(__pyx_k_ACCEPTOR), 0, 0, 1, 1},
@@ -49369,21 +48233,23 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_ARC_SORT_PROPERTIES, __pyx_k_ARC_SORT_PROPERTIES, sizeof(__pyx_k_ARC_SORT_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_ARC_VALUE_FLAGS, __pyx_k_ARC_VALUE_FLAGS, sizeof(__pyx_k_ARC_VALUE_FLAGS), 0, 0, 1, 1},
   {&__pyx_n_s_ARC_WEIGHT_VALUE, __pyx_k_ARC_WEIGHT_VALUE, sizeof(__pyx_k_ARC_WEIGHT_VALUE), 0, 0, 1, 1},
-  {&__pyx_kp_s_ArcIterator_at_0x_x, __pyx_k_ArcIterator_at_0x_x, sizeof(__pyx_k_ArcIterator_at_0x_x), 0, 0, 1, 0},
-  {&__pyx_kp_s_Arc_at_0x_x, __pyx_k_Arc_at_0x_x, sizeof(__pyx_k_Arc_at_0x_x), 0, 0, 1, 0},
+  {&__pyx_n_s_Arc, __pyx_k_Arc, sizeof(__pyx_k_Arc), 0, 0, 1, 1},
+  {&__pyx_n_s_ArcIterator, __pyx_k_ArcIterator, sizeof(__pyx_k_ArcIterator), 0, 0, 1, 1},
+  {&__pyx_kp_u_ArcIterator_at_0x_x, __pyx_k_ArcIterator_at_0x_x, sizeof(__pyx_k_ArcIterator_at_0x_x), 0, 1, 0, 0},
+  {&__pyx_kp_u_Arc_at_0x_x, __pyx_k_Arc_at_0x_x, sizeof(__pyx_k_Arc_at_0x_x), 0, 1, 0, 0},
   {&__pyx_n_s_BINARY_PROPERTIES, __pyx_k_BINARY_PROPERTIES, sizeof(__pyx_k_BINARY_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_COACCESSIBLE, __pyx_k_COACCESSIBLE, sizeof(__pyx_k_COACCESSIBLE), 0, 0, 1, 1},
   {&__pyx_n_s_COPY_PROPERTIES, __pyx_k_COPY_PROPERTIES, sizeof(__pyx_k_COPY_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_CYCLIC, __pyx_k_CYCLIC, sizeof(__pyx_k_CYCLIC), 0, 0, 1, 1},
-  {&__pyx_n_s_CalledProcessError, __pyx_k_CalledProcessError, sizeof(__pyx_k_CalledProcessError), 0, 0, 1, 1},
-  {&__pyx_kp_s_Cannot_construct, __pyx_k_Cannot_construct, sizeof(__pyx_k_Cannot_construct), 0, 0, 1, 0},
-  {&__pyx_kp_s_Cannot_encode_as_string_r, __pyx_k_Cannot_encode_as_string_r, sizeof(__pyx_k_Cannot_encode_as_string_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Cannot_topsort_cyclic_FST, __pyx_k_Cannot_topsort_cyclic_FST, sizeof(__pyx_k_Cannot_topsort_cyclic_FST), 0, 0, 1, 0},
-  {&__pyx_kp_s_Compilation_failed, __pyx_k_Compilation_failed, sizeof(__pyx_k_Compilation_failed), 0, 0, 1, 0},
-  {&__pyx_kp_s_Conversion_to_r_failed, __pyx_k_Conversion_to_r_failed, sizeof(__pyx_k_Conversion_to_r_failed), 0, 0, 1, 0},
+  {&__pyx_kp_u_Cannot_construct, __pyx_k_Cannot_construct, sizeof(__pyx_k_Cannot_construct), 0, 1, 0, 0},
+  {&__pyx_kp_u_Cannot_encode_as_string_r, __pyx_k_Cannot_encode_as_string_r, sizeof(__pyx_k_Cannot_encode_as_string_r), 0, 1, 0, 0},
+  {&__pyx_kp_u_Cannot_topsort_cyclic_FST, __pyx_k_Cannot_topsort_cyclic_FST, sizeof(__pyx_k_Cannot_topsort_cyclic_FST), 0, 1, 0, 0},
+  {&__pyx_kp_u_Compilation_failed, __pyx_k_Compilation_failed, sizeof(__pyx_k_Compilation_failed), 0, 1, 0, 0},
+  {&__pyx_n_s_Compiler, __pyx_k_Compiler, sizeof(__pyx_k_Compiler), 0, 0, 1, 1},
+  {&__pyx_kp_u_Conversion_to_r_failed, __pyx_k_Conversion_to_r_failed, sizeof(__pyx_k_Conversion_to_r_failed), 0, 1, 0, 0},
   {&__pyx_n_s_DELETE_ARC_PROPERTIES, __pyx_k_DELETE_ARC_PROPERTIES, sizeof(__pyx_k_DELETE_ARC_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_DELETE_STATE_PROPERTIES, __pyx_k_DELETE_STATE_PROPERTIES, sizeof(__pyx_k_DELETE_STATE_PROPERTIES), 0, 0, 1, 1},
-  {&__pyx_n_s_DOT_TSVG, __pyx_k_DOT_TSVG, sizeof(__pyx_k_DOT_TSVG), 0, 0, 1, 1},
+  {&__pyx_kp_u_Dot_rendering_failed, __pyx_k_Dot_rendering_failed, sizeof(__pyx_k_Dot_rendering_failed), 0, 1, 0, 0},
   {&__pyx_n_s_ENCODE_FLAGS, __pyx_k_ENCODE_FLAGS, sizeof(__pyx_k_ENCODE_FLAGS), 0, 0, 1, 1},
   {&__pyx_n_s_ENCODE_LABELS, __pyx_k_ENCODE_LABELS, sizeof(__pyx_k_ENCODE_LABELS), 0, 0, 1, 1},
   {&__pyx_n_s_ENCODE_WEIGHTS, __pyx_k_ENCODE_WEIGHTS, sizeof(__pyx_k_ENCODE_WEIGHTS), 0, 0, 1, 1},
@@ -49391,10 +48257,14 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_ERROR, __pyx_k_ERROR, sizeof(__pyx_k_ERROR), 0, 0, 1, 1},
   {&__pyx_n_s_EXPANDED, __pyx_k_EXPANDED, sizeof(__pyx_k_EXPANDED), 0, 0, 1, 1},
   {&__pyx_n_s_EXTRINSIC_PROPERTIES, __pyx_k_EXTRINSIC_PROPERTIES, sizeof(__pyx_k_EXTRINSIC_PROPERTIES), 0, 0, 1, 1},
-  {&__pyx_kp_s_EncodeMapper_at_0x_x, __pyx_k_EncodeMapper_at_0x_x, sizeof(__pyx_k_EncodeMapper_at_0x_x), 0, 0, 1, 0},
+  {&__pyx_n_s_EncodeMapper, __pyx_k_EncodeMapper, sizeof(__pyx_k_EncodeMapper), 0, 0, 1, 1},
+  {&__pyx_n_s_EncodeMapperSymbolTable, __pyx_k_EncodeMapperSymbolTable, sizeof(__pyx_k_EncodeMapperSymbolTable), 0, 0, 1, 1},
+  {&__pyx_kp_u_EncodeMapper_at_0x_x, __pyx_k_EncodeMapper_at_0x_x, sizeof(__pyx_k_EncodeMapper_at_0x_x), 0, 1, 0, 0},
   {&__pyx_n_s_FST_PROPERTIES, __pyx_k_FST_PROPERTIES, sizeof(__pyx_k_FST_PROPERTIES), 0, 0, 1, 1},
-  {&__pyx_kp_s_FarReader_at_0x_x, __pyx_k_FarReader_at_0x_x, sizeof(__pyx_k_FarReader_at_0x_x), 0, 0, 1, 0},
-  {&__pyx_kp_s_FarWriter_at_0x_x, __pyx_k_FarWriter_at_0x_x, sizeof(__pyx_k_FarWriter_at_0x_x), 0, 0, 1, 0},
+  {&__pyx_n_s_FarReader, __pyx_k_FarReader, sizeof(__pyx_k_FarReader), 0, 0, 1, 1},
+  {&__pyx_kp_u_FarReader_at_0x_x, __pyx_k_FarReader_at_0x_x, sizeof(__pyx_k_FarReader_at_0x_x), 0, 1, 0, 0},
+  {&__pyx_n_s_FarWriter, __pyx_k_FarWriter, sizeof(__pyx_k_FarWriter), 0, 0, 1, 1},
+  {&__pyx_kp_u_FarWriter_at_0x_x, __pyx_k_FarWriter_at_0x_x, sizeof(__pyx_k_FarWriter_at_0x_x), 0, 1, 0, 0},
   {&__pyx_n_s_Fst, __pyx_k_Fst, sizeof(__pyx_k_Fst), 0, 0, 1, 1},
   {&__pyx_n_s_FstArgError, __pyx_k_FstArgError, sizeof(__pyx_k_FstArgError), 0, 0, 1, 1},
   {&__pyx_n_s_FstBadWeightError, __pyx_k_FstBadWeightError, sizeof(__pyx_k_FstBadWeightError), 0, 0, 1, 1},
@@ -49403,10 +48273,12 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_FstIOError, __pyx_k_FstIOError, sizeof(__pyx_k_FstIOError), 0, 0, 1, 1},
   {&__pyx_n_s_FstIndexError, __pyx_k_FstIndexError, sizeof(__pyx_k_FstIndexError), 0, 0, 1, 1},
   {&__pyx_n_s_FstOpError, __pyx_k_FstOpError, sizeof(__pyx_k_FstOpError), 0, 0, 1, 1},
-  {&__pyx_kp_s_Fst_SymbolTable_r_at_0x_x, __pyx_k_Fst_SymbolTable_r_at_0x_x, sizeof(__pyx_k_Fst_SymbolTable_r_at_0x_x), 0, 0, 1, 0},
+  {&__pyx_n_s_FstSymbolTable, __pyx_k_FstSymbolTable, sizeof(__pyx_k_FstSymbolTable), 0, 0, 1, 1},
+  {&__pyx_n_s_Fst_2, __pyx_k_Fst_2, sizeof(__pyx_k_Fst_2), 0, 0, 1, 1},
+  {&__pyx_kp_u_Fst_SymbolTable_r_at_0x_x, __pyx_k_Fst_SymbolTable_r_at_0x_x, sizeof(__pyx_k_Fst_SymbolTable_r_at_0x_x), 0, 1, 0, 0},
   {&__pyx_n_s_Fst___new, __pyx_k_Fst___new, sizeof(__pyx_k_Fst___new), 0, 0, 1, 1},
   {&__pyx_kp_s_Fst_arc_type_standard_Construct, __pyx_k_Fst_arc_type_standard_Construct, sizeof(__pyx_k_Fst_arc_type_standard_Construct), 0, 0, 1, 0},
-  {&__pyx_kp_s_Fst_at_0x_x, __pyx_k_Fst_at_0x_x, sizeof(__pyx_k_Fst_at_0x_x), 0, 0, 1, 0},
+  {&__pyx_kp_u_Fst_at_0x_x, __pyx_k_Fst_at_0x_x, sizeof(__pyx_k_Fst_at_0x_x), 0, 1, 0, 0},
   {&__pyx_n_s_Fst_read, __pyx_k_Fst_read, sizeof(__pyx_k_Fst_read), 0, 0, 1, 1},
   {&__pyx_n_s_Fst_read_from_string, __pyx_k_Fst_read_from_string, sizeof(__pyx_k_Fst_read_from_string), 0, 0, 1, 1},
   {&__pyx_n_s_INITIAL_ACYCLIC, __pyx_k_INITIAL_ACYCLIC, sizeof(__pyx_k_INITIAL_ACYCLIC), 0, 0, 1, 1},
@@ -49417,15 +48289,19 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_I_EPSILONS, __pyx_k_I_EPSILONS, sizeof(__pyx_k_I_EPSILONS), 0, 0, 1, 1},
   {&__pyx_n_s_I_LABEL_INVARIANT_PROPERTIES, __pyx_k_I_LABEL_INVARIANT_PROPERTIES, sizeof(__pyx_k_I_LABEL_INVARIANT_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_I_LABEL_SORTED, __pyx_k_I_LABEL_SORTED, sizeof(__pyx_k_I_LABEL_SORTED), 0, 0, 1, 1},
-  {&__pyx_kp_s_Incompatible_or_invalid_arc_type, __pyx_k_Incompatible_or_invalid_arc_type, sizeof(__pyx_k_Incompatible_or_invalid_arc_type), 0, 0, 1, 0},
-  {&__pyx_kp_s_Incompatible_or_invalid_weight, __pyx_k_Incompatible_or_invalid_weight, sizeof(__pyx_k_Incompatible_or_invalid_weight), 0, 0, 1, 0},
-  {&__pyx_kp_s_Incompatible_or_invalid_weight_t, __pyx_k_Incompatible_or_invalid_weight_t, sizeof(__pyx_k_Incompatible_or_invalid_weight_t), 0, 0, 1, 0},
+  {&__pyx_kp_u_Incompatible_or_invalid_arc_type, __pyx_k_Incompatible_or_invalid_arc_type, sizeof(__pyx_k_Incompatible_or_invalid_arc_type), 0, 1, 0, 0},
+  {&__pyx_kp_u_Incompatible_or_invalid_weight, __pyx_k_Incompatible_or_invalid_weight, sizeof(__pyx_k_Incompatible_or_invalid_weight), 0, 1, 0, 0},
+  {&__pyx_kp_u_Incompatible_or_invalid_weight_t, __pyx_k_Incompatible_or_invalid_weight_t, sizeof(__pyx_k_Incompatible_or_invalid_weight_t), 0, 1, 0, 0},
   {&__pyx_n_s_IndexError, __pyx_k_IndexError, sizeof(__pyx_k_IndexError), 0, 0, 1, 1},
-  {&__pyx_kp_s_Invalid_weight, __pyx_k_Invalid_weight, sizeof(__pyx_k_Invalid_weight), 0, 0, 1, 0},
+  {&__pyx_kp_u_Invalid_weight, __pyx_k_Invalid_weight, sizeof(__pyx_k_Invalid_weight), 0, 1, 0, 0},
   {&__pyx_n_s_KeyError, __pyx_k_KeyError, sizeof(__pyx_k_KeyError), 0, 0, 1, 1},
-  {&__pyx_kp_s_Key_out_of_order, __pyx_k_Key_out_of_order, sizeof(__pyx_k_Key_out_of_order), 0, 0, 1, 0},
+  {&__pyx_kp_u_Key_out_of_order, __pyx_k_Key_out_of_order, sizeof(__pyx_k_Key_out_of_order), 0, 1, 0, 0},
   {&__pyx_n_s_MUTABLE, __pyx_k_MUTABLE, sizeof(__pyx_k_MUTABLE), 0, 0, 1, 1},
-  {&__pyx_kp_s_MutableArcIterator_at_0x_x, __pyx_k_MutableArcIterator_at_0x_x, sizeof(__pyx_k_MutableArcIterator_at_0x_x), 0, 0, 1, 0},
+  {&__pyx_n_s_MutableArcIterator, __pyx_k_MutableArcIterator, sizeof(__pyx_k_MutableArcIterator), 0, 0, 1, 1},
+  {&__pyx_kp_u_MutableArcIterator_at_0x_x, __pyx_k_MutableArcIterator_at_0x_x, sizeof(__pyx_k_MutableArcIterator_at_0x_x), 0, 1, 0, 0},
+  {&__pyx_n_s_MutableFst, __pyx_k_MutableFst, sizeof(__pyx_k_MutableFst), 0, 0, 1, 1},
+  {&__pyx_n_s_MutableFstSymbolTable, __pyx_k_MutableFstSymbolTable, sizeof(__pyx_k_MutableFstSymbolTable), 0, 0, 1, 1},
+  {&__pyx_n_s_MutableSymbolTable, __pyx_k_MutableSymbolTable, sizeof(__pyx_k_MutableSymbolTable), 0, 0, 1, 1},
   {&__pyx_n_s_NEG_TRINARY_PROPERTIES, __pyx_k_NEG_TRINARY_PROPERTIES, sizeof(__pyx_k_NEG_TRINARY_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_NON_I_DETERMINISTIC, __pyx_k_NON_I_DETERMINISTIC, sizeof(__pyx_k_NON_I_DETERMINISTIC), 0, 0, 1, 1},
   {&__pyx_n_s_NON_O_DETERMINISTIC, __pyx_k_NON_O_DETERMINISTIC, sizeof(__pyx_k_NON_O_DETERMINISTIC), 0, 0, 1, 1},
@@ -49444,57 +48320,62 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_NO_SYMBOL, __pyx_k_NO_SYMBOL, sizeof(__pyx_k_NO_SYMBOL), 0, 0, 1, 1},
   {&__pyx_n_s_NULL_PROPERTIES, __pyx_k_NULL_PROPERTIES, sizeof(__pyx_k_NULL_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_NoWeight, __pyx_k_NoWeight, sizeof(__pyx_k_NoWeight), 0, 0, 1, 1},
-  {&__pyx_kp_s_No_new_SymbolTables_specified, __pyx_k_No_new_SymbolTables_specified, sizeof(__pyx_k_No_new_SymbolTables_specified), 0, 0, 1, 0},
-  {&__pyx_kp_s_No_relabeling_pairs_specified, __pyx_k_No_relabeling_pairs_specified, sizeof(__pyx_k_No_relabeling_pairs_specified), 0, 0, 1, 0},
+  {&__pyx_kp_u_No_new_SymbolTables_specified, __pyx_k_No_new_SymbolTables_specified, sizeof(__pyx_k_No_new_SymbolTables_specified), 0, 1, 0, 0},
+  {&__pyx_kp_u_No_relabeling_pairs_specified, __pyx_k_No_relabeling_pairs_specified, sizeof(__pyx_k_No_relabeling_pairs_specified), 0, 1, 0, 0},
   {&__pyx_n_s_Number, __pyx_k_Number, sizeof(__pyx_k_Number), 0, 0, 1, 1},
   {&__pyx_n_s_O_DETERMINISTIC, __pyx_k_O_DETERMINISTIC, sizeof(__pyx_k_O_DETERMINISTIC), 0, 0, 1, 1},
   {&__pyx_n_s_O_EPSILONS, __pyx_k_O_EPSILONS, sizeof(__pyx_k_O_EPSILONS), 0, 0, 1, 1},
   {&__pyx_n_s_O_LABEL_INVARIANT_PROPERTIES, __pyx_k_O_LABEL_INVARIANT_PROPERTIES, sizeof(__pyx_k_O_LABEL_INVARIANT_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_O_LABEL_SORTED, __pyx_k_O_LABEL_SORTED, sizeof(__pyx_k_O_LABEL_SORTED), 0, 0, 1, 1},
   {&__pyx_n_s_One, __pyx_k_One, sizeof(__pyx_k_One), 0, 0, 1, 1},
-  {&__pyx_kp_s_Open_failed_r, __pyx_k_Open_failed_r, sizeof(__pyx_k_Open_failed_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Operation_failed, __pyx_k_Operation_failed, sizeof(__pyx_k_Operation_failed), 0, 0, 1, 0},
+  {&__pyx_kp_u_Open_failed_r, __pyx_k_Open_failed_r, sizeof(__pyx_k_Open_failed_r), 0, 1, 0, 0},
+  {&__pyx_kp_u_Operation_failed, __pyx_k_Operation_failed, sizeof(__pyx_k_Operation_failed), 0, 1, 0, 0},
   {&__pyx_n_s_PIPE, __pyx_k_PIPE, sizeof(__pyx_k_PIPE), 0, 0, 1, 1},
   {&__pyx_n_s_POS_TRINARY_PROPERTIES, __pyx_k_POS_TRINARY_PROPERTIES, sizeof(__pyx_k_POS_TRINARY_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_Popen, __pyx_k_Popen, sizeof(__pyx_k_Popen), 0, 0, 1, 1},
   {&__pyx_n_s_RM_SUPERFINAL_PROPERTIES, __pyx_k_RM_SUPERFINAL_PROPERTIES, sizeof(__pyx_k_RM_SUPERFINAL_PROPERTIES), 0, 0, 1, 1},
-  {&__pyx_kp_s_Read_failed_r, __pyx_k_Read_failed_r, sizeof(__pyx_k_Read_failed_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Read_failed_string, __pyx_k_Read_failed_string, sizeof(__pyx_k_Read_failed_string), 0, 0, 1, 0},
+  {&__pyx_kp_u_Read_failed, __pyx_k_Read_failed, sizeof(__pyx_k_Read_failed), 0, 1, 0, 0},
+  {&__pyx_kp_u_Read_failed_r, __pyx_k_Read_failed_r, sizeof(__pyx_k_Read_failed_r), 0, 1, 0, 0},
   {&__pyx_n_s_RuntimeError, __pyx_k_RuntimeError, sizeof(__pyx_k_RuntimeError), 0, 0, 1, 1},
   {&__pyx_n_s_SET_ARC_PROPERTIES, __pyx_k_SET_ARC_PROPERTIES, sizeof(__pyx_k_SET_ARC_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_SET_FINAL_PROPERTIES, __pyx_k_SET_FINAL_PROPERTIES, sizeof(__pyx_k_SET_FINAL_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_SET_START_PROPERTIES, __pyx_k_SET_START_PROPERTIES, sizeof(__pyx_k_SET_START_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_STATE_SORT_PROPERTIES, __pyx_k_STATE_SORT_PROPERTIES, sizeof(__pyx_k_STATE_SORT_PROPERTIES), 0, 0, 1, 1},
   {&__pyx_n_s_STRING, __pyx_k_STRING, sizeof(__pyx_k_STRING), 0, 0, 1, 1},
-  {&__pyx_kp_s_StateIterator_at_0x_x, __pyx_k_StateIterator_at_0x_x, sizeof(__pyx_k_StateIterator_at_0x_x), 0, 0, 1, 0},
-  {&__pyx_kp_s_State_index_out_of_range, __pyx_k_State_index_out_of_range, sizeof(__pyx_k_State_index_out_of_range), 0, 0, 1, 0},
+  {&__pyx_n_s_StateIterator, __pyx_k_StateIterator, sizeof(__pyx_k_StateIterator), 0, 0, 1, 1},
+  {&__pyx_kp_u_StateIterator_at_0x_x, __pyx_k_StateIterator_at_0x_x, sizeof(__pyx_k_StateIterator_at_0x_x), 0, 1, 0, 0},
+  {&__pyx_kp_u_State_index_out_of_range, __pyx_k_State_index_out_of_range, sizeof(__pyx_k_State_index_out_of_range), 0, 1, 0, 0},
   {&__pyx_n_s_StopIteration, __pyx_k_StopIteration, sizeof(__pyx_k_StopIteration), 0, 0, 1, 1},
-  {&__pyx_kp_s_SymbolTableIterator_at_0x_x, __pyx_k_SymbolTableIterator_at_0x_x, sizeof(__pyx_k_SymbolTableIterator_at_0x_x), 0, 0, 1, 0},
-  {&__pyx_kp_s_SymbolTable_r_at_0x_x, __pyx_k_SymbolTable_r_at_0x_x, sizeof(__pyx_k_SymbolTable_r_at_0x_x), 0, 0, 1, 0},
+  {&__pyx_n_s_SymbolTable, __pyx_k_SymbolTable, sizeof(__pyx_k_SymbolTable), 0, 0, 1, 1},
+  {&__pyx_n_s_SymbolTableIterator, __pyx_k_SymbolTableIterator, sizeof(__pyx_k_SymbolTableIterator), 0, 0, 1, 1},
+  {&__pyx_kp_u_SymbolTableIterator_at_0x_x, __pyx_k_SymbolTableIterator_at_0x_x, sizeof(__pyx_k_SymbolTableIterator_at_0x_x), 0, 1, 0, 0},
+  {&__pyx_n_s_SymbolTable_2, __pyx_k_SymbolTable_2, sizeof(__pyx_k_SymbolTable_2), 0, 0, 1, 1},
+  {&__pyx_kp_u_SymbolTable_r_at_0x_x, __pyx_k_SymbolTable_r_at_0x_x, sizeof(__pyx_k_SymbolTable_r_at_0x_x), 0, 1, 0, 0},
   {&__pyx_n_s_TOP_SORTED, __pyx_k_TOP_SORTED, sizeof(__pyx_k_TOP_SORTED), 0, 0, 1, 1},
   {&__pyx_n_s_TRINARY_PROPERTIES, __pyx_k_TRINARY_PROPERTIES, sizeof(__pyx_k_TRINARY_PROPERTIES), 0, 0, 1, 1},
-  {&__pyx_kp_s_Tsvg, __pyx_k_Tsvg, sizeof(__pyx_k_Tsvg), 0, 0, 1, 0},
+  {&__pyx_kp_u_Tsvg, __pyx_k_Tsvg, sizeof(__pyx_k_Tsvg), 0, 1, 0, 0},
   {&__pyx_n_s_TypeError, __pyx_k_TypeError, sizeof(__pyx_k_TypeError), 0, 0, 1, 1},
   {&__pyx_n_s_UNWEIGHTED, __pyx_k_UNWEIGHTED, sizeof(__pyx_k_UNWEIGHTED), 0, 0, 1, 1},
   {&__pyx_n_s_UNWEIGHTED_CYCLES, __pyx_k_UNWEIGHTED_CYCLES, sizeof(__pyx_k_UNWEIGHTED_CYCLES), 0, 0, 1, 1},
-  {&__pyx_kp_s_Unknown_arc_type_r, __pyx_k_Unknown_arc_type_r, sizeof(__pyx_k_Unknown_arc_type_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Unknown_compose_filter_type_r, __pyx_k_Unknown_compose_filter_type_r, sizeof(__pyx_k_Unknown_compose_filter_type_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Unknown_determinization_type_r, __pyx_k_Unknown_determinization_type_r, sizeof(__pyx_k_Unknown_determinization_type_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Unknown_map_type_r, __pyx_k_Unknown_map_type_r, sizeof(__pyx_k_Unknown_map_type_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Unknown_queue_type_r, __pyx_k_Unknown_queue_type_r, sizeof(__pyx_k_Unknown_queue_type_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Unknown_random_arc_selection_typ, __pyx_k_Unknown_random_arc_selection_typ, sizeof(__pyx_k_Unknown_random_arc_selection_typ), 0, 0, 1, 0},
-  {&__pyx_kp_s_Unknown_replace_label_type_r, __pyx_k_Unknown_replace_label_type_r, sizeof(__pyx_k_Unknown_replace_label_type_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Unknown_sort_type_r, __pyx_k_Unknown_sort_type_r, sizeof(__pyx_k_Unknown_sort_type_r), 0, 0, 1, 0},
+  {&__pyx_kp_u_Unknown_arc_type_r, __pyx_k_Unknown_arc_type_r, sizeof(__pyx_k_Unknown_arc_type_r), 0, 1, 0, 0},
+  {&__pyx_kp_u_Unknown_compose_filter_type_r, __pyx_k_Unknown_compose_filter_type_r, sizeof(__pyx_k_Unknown_compose_filter_type_r), 0, 1, 0, 0},
+  {&__pyx_kp_u_Unknown_determinization_type_r, __pyx_k_Unknown_determinization_type_r, sizeof(__pyx_k_Unknown_determinization_type_r), 0, 1, 0, 0},
+  {&__pyx_kp_u_Unknown_map_type_r, __pyx_k_Unknown_map_type_r, sizeof(__pyx_k_Unknown_map_type_r), 0, 1, 0, 0},
+  {&__pyx_kp_u_Unknown_queue_type_r, __pyx_k_Unknown_queue_type_r, sizeof(__pyx_k_Unknown_queue_type_r), 0, 1, 0, 0},
+  {&__pyx_kp_u_Unknown_random_arc_selection_typ, __pyx_k_Unknown_random_arc_selection_typ, sizeof(__pyx_k_Unknown_random_arc_selection_typ), 0, 1, 0, 0},
+  {&__pyx_kp_u_Unknown_replace_label_type_r, __pyx_k_Unknown_replace_label_type_r, sizeof(__pyx_k_Unknown_replace_label_type_r), 0, 1, 0, 0},
+  {&__pyx_kp_u_Unknown_sort_type_r, __pyx_k_Unknown_sort_type_r, sizeof(__pyx_k_Unknown_sort_type_r), 0, 1, 0, 0},
   {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1},
   {&__pyx_n_s_WEIGHTED, __pyx_k_WEIGHTED, sizeof(__pyx_k_WEIGHTED), 0, 0, 1, 1},
   {&__pyx_n_s_WEIGHTED_CYCLES, __pyx_k_WEIGHTED_CYCLES, sizeof(__pyx_k_WEIGHTED_CYCLES), 0, 0, 1, 1},
   {&__pyx_n_s_WEIGHT_INVARIANT_PROPERTIES, __pyx_k_WEIGHT_INVARIANT_PROPERTIES, sizeof(__pyx_k_WEIGHT_INVARIANT_PROPERTIES), 0, 0, 1, 1},
-  {&__pyx_kp_s_Weight_at_0x_x, __pyx_k_Weight_at_0x_x, sizeof(__pyx_k_Weight_at_0x_x), 0, 0, 1, 0},
-  {&__pyx_kp_s_Weight_type_not_found, __pyx_k_Weight_type_not_found, sizeof(__pyx_k_Weight_type_not_found), 0, 0, 1, 0},
-  {&__pyx_kp_s_Write_failed_r, __pyx_k_Write_failed_r, sizeof(__pyx_k_Write_failed_r), 0, 0, 1, 0},
-  {&__pyx_kp_s_Write_to_string_failed, __pyx_k_Write_to_string_failed, sizeof(__pyx_k_Write_to_string_failed), 0, 0, 1, 0},
+  {&__pyx_n_s_Weight, __pyx_k_Weight, sizeof(__pyx_k_Weight), 0, 0, 1, 1},
+  {&__pyx_kp_u_Weight_at_0x_x, __pyx_k_Weight_at_0x_x, sizeof(__pyx_k_Weight_at_0x_x), 0, 1, 0, 0},
+  {&__pyx_kp_u_Weight_type_not_found, __pyx_k_Weight_type_not_found, sizeof(__pyx_k_Weight_type_not_found), 0, 1, 0, 0},
+  {&__pyx_kp_u_Write_failed_r, __pyx_k_Write_failed_r, sizeof(__pyx_k_Write_failed_r), 0, 1, 0, 0},
+  {&__pyx_kp_u_Write_to_string_failed, __pyx_k_Write_to_string_failed, sizeof(__pyx_k_Write_to_string_failed), 0, 1, 0, 0},
   {&__pyx_n_s_Zero, __pyx_k_Zero, sizeof(__pyx_k_Zero), 0, 0, 1, 1},
-  {&__pyx_kp_b__24, __pyx_k__24, sizeof(__pyx_k__24), 0, 0, 0, 0},
+  {&__pyx_kp_b__10, __pyx_k__10, sizeof(__pyx_k__10), 0, 0, 0, 0},
   {&__pyx_n_s_acceptor, __pyx_k_acceptor, sizeof(__pyx_k_acceptor), 0, 0, 1, 1},
   {&__pyx_n_s_add, __pyx_k_add, sizeof(__pyx_k_add), 0, 0, 1, 1},
   {&__pyx_n_s_add_state, __pyx_k_add_state, sizeof(__pyx_k_add_state), 0, 0, 1, 1},
@@ -49505,7 +48386,6 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_arc, __pyx_k_arc, sizeof(__pyx_k_arc), 0, 0, 1, 1},
   {&__pyx_n_s_arc_type, __pyx_k_arc_type, sizeof(__pyx_k_arc_type), 0, 0, 1, 1},
   {&__pyx_n_s_arcs, __pyx_k_arcs, sizeof(__pyx_k_arcs), 0, 0, 1, 1},
-  {&__pyx_n_s_atexit, __pyx_k_atexit, sizeof(__pyx_k_atexit), 0, 0, 1, 1},
   {&__pyx_n_s_attach_new_isymbols, __pyx_k_attach_new_isymbols, sizeof(__pyx_k_attach_new_isymbols), 0, 0, 1, 1},
   {&__pyx_n_s_attach_new_osymbols, __pyx_k_attach_new_osymbols, sizeof(__pyx_k_attach_new_osymbols), 0, 0, 1, 1},
   {&__pyx_n_b_auto, __pyx_k_auto, sizeof(__pyx_k_auto), 0, 0, 0, 1},
@@ -49520,11 +48400,10 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_compile, __pyx_k_compile, sizeof(__pyx_k_compile), 0, 0, 1, 1},
   {&__pyx_n_s_compose_filter, __pyx_k_compose_filter, sizeof(__pyx_k_compose_filter), 0, 0, 1, 1},
   {&__pyx_n_s_connect, __pyx_k_connect, sizeof(__pyx_k_connect), 0, 0, 1, 1},
-  {&__pyx_kp_s_const_EncodeMapper_SymbolTable, __pyx_k_const_EncodeMapper_SymbolTable, sizeof(__pyx_k_const_EncodeMapper_SymbolTable), 0, 0, 1, 0},
-  {&__pyx_kp_s_const_Fst_SymbolTable_r_at_0x_x, __pyx_k_const_Fst_SymbolTable_r_at_0x_x, sizeof(__pyx_k_const_Fst_SymbolTable_r_at_0x_x), 0, 0, 1, 0},
+  {&__pyx_kp_u_const_EncodeMapper_SymbolTable, __pyx_k_const_EncodeMapper_SymbolTable, sizeof(__pyx_k_const_EncodeMapper_SymbolTable), 0, 1, 0, 0},
+  {&__pyx_kp_u_const_Fst_SymbolTable_r_at_0x_x, __pyx_k_const_Fst_SymbolTable_r_at_0x_x, sizeof(__pyx_k_const_Fst_SymbolTable_r_at_0x_x), 0, 1, 0, 0},
   {&__pyx_n_s_copy, __pyx_k_copy, sizeof(__pyx_k_copy), 0, 0, 1, 1},
   {&__pyx_n_s_create, __pyx_k_create, sizeof(__pyx_k_create), 0, 0, 1, 1},
-  {&__pyx_n_s_decode, __pyx_k_decode, sizeof(__pyx_k_decode), 0, 0, 1, 1},
   {&__pyx_n_b_default, __pyx_k_default, sizeof(__pyx_k_default), 0, 0, 0, 1},
   {&__pyx_n_s_delta, __pyx_k_delta, sizeof(__pyx_k_delta), 0, 0, 1, 1},
   {&__pyx_n_s_det_type, __pyx_k_det_type, sizeof(__pyx_k_det_type), 0, 0, 1, 1},
@@ -49532,7 +48411,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_divide, __pyx_k_divide, sizeof(__pyx_k_divide), 0, 0, 1, 1},
   {&__pyx_n_s_doc, __pyx_k_doc, sizeof(__pyx_k_doc), 0, 0, 1, 1},
   {&__pyx_n_s_done, __pyx_k_done, sizeof(__pyx_k_done), 0, 0, 1, 1},
-  {&__pyx_n_s_dot, __pyx_k_dot, sizeof(__pyx_k_dot), 0, 0, 1, 1},
+  {&__pyx_n_u_dot, __pyx_k_dot, sizeof(__pyx_k_dot), 0, 1, 0, 1},
   {&__pyx_n_s_draw, __pyx_k_draw, sizeof(__pyx_k_draw), 0, 0, 1, 1},
   {&__pyx_n_s_encode, __pyx_k_encode, sizeof(__pyx_k_encode), 0, 0, 1, 1},
   {&__pyx_n_s_encode_labels, __pyx_k_encode_labels, sizeof(__pyx_k_encode_labels), 0, 0, 1, 1},
@@ -49548,7 +48427,6 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_float_format, __pyx_k_float_format, sizeof(__pyx_k_float_format), 0, 0, 1, 1},
   {&__pyx_n_s_fontsize, __pyx_k_fontsize, sizeof(__pyx_k_fontsize), 0, 0, 1, 1},
   {&__pyx_n_s_format, __pyx_k_format, sizeof(__pyx_k_format), 0, 0, 1, 1},
-  {&__pyx_n_s_fst_error_fatal_old, __pyx_k_fst_error_fatal_old, sizeof(__pyx_k_fst_error_fatal_old), 0, 0, 1, 1},
   {&__pyx_n_s_fst_type, __pyx_k_fst_type, sizeof(__pyx_k_fst_type), 0, 0, 1, 1},
   {&__pyx_n_b_functional, __pyx_k_functional, sizeof(__pyx_k_functional), 0, 0, 0, 1},
   {&__pyx_n_b_g, __pyx_k_g, sizeof(__pyx_k_g), 0, 0, 0, 1},
@@ -49571,7 +48449,6 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_input_table, __pyx_k_input_table, sizeof(__pyx_k_input_table), 0, 0, 1, 1},
   {&__pyx_n_s_ipairs, __pyx_k_ipairs, sizeof(__pyx_k_ipairs), 0, 0, 1, 1},
   {&__pyx_n_s_isymbols, __pyx_k_isymbols, sizeof(__pyx_k_isymbols), 0, 0, 1, 1},
-  {&__pyx_n_s_kNoSymbol, __pyx_k_kNoSymbol, sizeof(__pyx_k_kNoSymbol), 0, 0, 1, 1},
   {&__pyx_n_s_keep_isymbols, __pyx_k_keep_isymbols, sizeof(__pyx_k_keep_isymbols), 0, 0, 1, 1},
   {&__pyx_n_s_keep_osymbols, __pyx_k_keep_osymbols, sizeof(__pyx_k_keep_osymbols), 0, 0, 1, 1},
   {&__pyx_n_s_keep_state_numbering, __pyx_k_keep_state_numbering, sizeof(__pyx_k_keep_state_numbering), 0, 0, 1, 1},
@@ -49636,23 +48513,21 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s_queue_type, __pyx_k_queue_type, sizeof(__pyx_k_queue_type), 0, 0, 1, 1},
   {&__pyx_n_s_ranksep, __pyx_k_ranksep, sizeof(__pyx_k_ranksep), 0, 0, 1, 1},
   {&__pyx_n_s_read, __pyx_k_read, sizeof(__pyx_k_read), 0, 0, 1, 1},
+  {&__pyx_n_s_read_Fst_from_string, __pyx_k_read_Fst_from_string, sizeof(__pyx_k_read_Fst_from_string), 0, 0, 1, 1},
+  {&__pyx_n_s_read_SymbolTable_from_string, __pyx_k_read_SymbolTable_from_string, sizeof(__pyx_k_read_SymbolTable_from_string), 0, 0, 1, 1},
   {&__pyx_n_s_read_from_string, __pyx_k_read_from_string, sizeof(__pyx_k_read_from_string), 0, 0, 1, 1},
-  {&__pyx_n_s_read_from_string_2, __pyx_k_read_from_string_2, sizeof(__pyx_k_read_from_string_2), 0, 0, 1, 1},
   {&__pyx_n_s_read_fst, __pyx_k_read_fst, sizeof(__pyx_k_read_fst), 0, 0, 1, 1},
   {&__pyx_n_s_read_text, __pyx_k_read_text, sizeof(__pyx_k_read_text), 0, 0, 1, 1},
   {&__pyx_n_s_reduce, __pyx_k_reduce, sizeof(__pyx_k_reduce), 0, 0, 1, 1},
   {&__pyx_n_s_reduce_cython, __pyx_k_reduce_cython, sizeof(__pyx_k_reduce_cython), 0, 0, 1, 1},
   {&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1},
-  {&__pyx_n_s_register, __pyx_k_register, sizeof(__pyx_k_register), 0, 0, 1, 1},
   {&__pyx_n_s_remove_common_affix, __pyx_k_remove_common_affix, sizeof(__pyx_k_remove_common_affix), 0, 0, 1, 1},
   {&__pyx_n_s_remove_total_weight, __pyx_k_remove_total_weight, sizeof(__pyx_k_remove_total_weight), 0, 0, 1, 1},
   {&__pyx_n_s_require_superinitial, __pyx_k_require_superinitial, sizeof(__pyx_k_require_superinitial), 0, 0, 1, 1},
   {&__pyx_n_s_reset, __pyx_k_reset, sizeof(__pyx_k_reset), 0, 0, 1, 1},
-  {&__pyx_n_s_reset_fst_error_fatal, __pyx_k_reset_fst_error_fatal, sizeof(__pyx_k_reset_fst_error_fatal), 0, 0, 1, 1},
   {&__pyx_n_s_result, __pyx_k_result, sizeof(__pyx_k_result), 0, 0, 1, 1},
   {&__pyx_n_s_return_arc_labeling, __pyx_k_return_arc_labeling, sizeof(__pyx_k_return_arc_labeling), 0, 0, 1, 1},
   {&__pyx_n_s_return_label, __pyx_k_return_label, sizeof(__pyx_k_return_label), 0, 0, 1, 1},
-  {&__pyx_n_s_returncode, __pyx_k_returncode, sizeof(__pyx_k_returncode), 0, 0, 1, 1},
   {&__pyx_n_s_reverse, __pyx_k_reverse, sizeof(__pyx_k_reverse), 0, 0, 1, 1},
   {&__pyx_n_s_rhs, __pyx_k_rhs, sizeof(__pyx_k_rhs), 0, 0, 1, 1},
   {&__pyx_n_s_seed, __pyx_k_seed, sizeof(__pyx_k_seed), 0, 0, 1, 1},
@@ -49662,264 +48537,100 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_s_self__aiter_self__mfst_cannot_be, __pyx_k_self__aiter_self__mfst_cannot_be, sizeof(__pyx_k_self__aiter_self__mfst_cannot_be), 0, 0, 1, 0},
   {&__pyx_kp_s_self__arc_cannot_be_converted_to, __pyx_k_self__arc_cannot_be_converted_to, sizeof(__pyx_k_self__arc_cannot_be_converted_to), 0, 0, 1, 0},
   {&__pyx_kp_s_self__encoder_cannot_be_converte, __pyx_k_self__encoder_cannot_be_converte, sizeof(__pyx_k_self__encoder_cannot_be_converte), 0, 0, 1, 0},
-  {&__pyx_kp_s_self__encoder_self__table_cannot, __pyx_k_self__encoder_self__table_cannot, sizeof(__pyx_k_self__encoder_self__table_cannot), 0, 0, 1, 0},
   {&__pyx_kp_s_self__fst_self__siter_cannot_be, __pyx_k_self__fst_self__siter_cannot_be, sizeof(__pyx_k_self__fst_self__siter_cannot_be), 0, 0, 1, 0},
-  {&__pyx_kp_s_self__fst_self__table_cannot_be, __pyx_k_self__fst_self__table_cannot_be, sizeof(__pyx_k_self__fst_self__table_cannot_be), 0, 0, 1, 0},
-  {&__pyx_kp_s_self__mfst_self__table_cannot_be, __pyx_k_self__mfst_self__table_cannot_be, sizeof(__pyx_k_self__mfst_self__table_cannot_be), 0, 0, 1, 0},
   {&__pyx_kp_s_self__reader_cannot_be_converted, __pyx_k_self__reader_cannot_be_converted, sizeof(__pyx_k_self__reader_cannot_be_converted), 0, 0, 1, 0},
   {&__pyx_kp_s_self__siter_self__table_cannot_b, __pyx_k_self__siter_self__table_cannot_b, sizeof(__pyx_k_self__siter_self__table_cannot_b), 0, 0, 1, 0},
-  {&__pyx_kp_s_self__smart_table_self__table_ca, __pyx_k_self__smart_table_self__table_ca, sizeof(__pyx_k_self__smart_table_self__table_ca), 0, 0, 1, 0},
-  {&__pyx_kp_s_self__table_cannot_be_converted, __pyx_k_self__table_cannot_be_converted, sizeof(__pyx_k_self__table_cannot_be_converted), 0, 0, 1, 0},
   {&__pyx_kp_s_self__weight_cannot_be_converted, __pyx_k_self__weight_cannot_be_converted, sizeof(__pyx_k_self__weight_cannot_be_converted), 0, 0, 1, 0},
-  {&__pyx_kp_s_self__writer_cannot_be_converted, __pyx_k_self__writer_cannot_be_converted, sizeof(__pyx_k_self__writer_cannot_be_converted), 0, 0, 1, 0},
-  {&__pyx_n_s_set_flags, __pyx_k_set_flags, sizeof(__pyx_k_set_flags), 0, 0, 1, 1},
-  {&__pyx_n_s_set_input_symbols, __pyx_k_set_input_symbols, sizeof(__pyx_k_set_input_symbols), 0, 0, 1, 1},
-  {&__pyx_n_s_set_name, __pyx_k_set_name, sizeof(__pyx_k_set_name), 0, 0, 1, 1},
-  {&__pyx_n_s_set_output_symbols, __pyx_k_set_output_symbols, sizeof(__pyx_k_set_output_symbols), 0, 0, 1, 1},
-  {&__pyx_n_s_set_value, __pyx_k_set_value, sizeof(__pyx_k_set_value), 0, 0, 1, 1},
-  {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1},
-  {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1},
-  {&__pyx_n_s_shortestdistance, __pyx_k_shortestdistance, sizeof(__pyx_k_shortestdistance), 0, 0, 1, 1},
-  {&__pyx_n_s_show_weight_one, __pyx_k_show_weight_one, sizeof(__pyx_k_show_weight_one), 0, 0, 1, 1},
-  {&__pyx_n_s_sort_type, __pyx_k_sort_type, sizeof(__pyx_k_sort_type), 0, 0, 1, 1},
-  {&__pyx_n_s_ssymbols, __pyx_k_ssymbols, sizeof(__pyx_k_ssymbols), 0, 0, 1, 1},
-  {&__pyx_n_b_standard, __pyx_k_standard, sizeof(__pyx_k_standard), 0, 0, 0, 1},
-  {&__pyx_n_s_start, __pyx_k_start, sizeof(__pyx_k_start), 0, 0, 1, 1},
-  {&__pyx_n_s_state, __pyx_k_state, sizeof(__pyx_k_state), 0, 0, 1, 1},
-  {&__pyx_n_s_states, __pyx_k_states, sizeof(__pyx_k_states), 0, 0, 1, 1},
-  {&__pyx_n_s_staticmethod, __pyx_k_staticmethod, sizeof(__pyx_k_staticmethod), 0, 0, 1, 1},
-  {&__pyx_n_s_stderr, __pyx_k_stderr, sizeof(__pyx_k_stderr), 0, 0, 1, 1},
-  {&__pyx_n_s_stdin, __pyx_k_stdin, sizeof(__pyx_k_stdin), 0, 0, 1, 1},
-  {&__pyx_n_s_stdout, __pyx_k_stdout, sizeof(__pyx_k_stdout), 0, 0, 1, 1},
-  {&__pyx_n_s_subprocess, __pyx_k_subprocess, sizeof(__pyx_k_subprocess), 0, 0, 1, 1},
-  {&__pyx_n_s_subsequential_label, __pyx_k_subsequential_label, sizeof(__pyx_k_subsequential_label), 0, 0, 1, 1},
-  {&__pyx_n_s_symbol, __pyx_k_symbol, sizeof(__pyx_k_symbol), 0, 0, 1, 1},
-  {&__pyx_n_s_syms, __pyx_k_syms, sizeof(__pyx_k_syms), 0, 0, 1, 1},
-  {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1},
-  {&__pyx_n_s_test_2, __pyx_k_test_2, sizeof(__pyx_k_test_2), 0, 0, 1, 1},
-  {&__pyx_n_s_text, __pyx_k_text, sizeof(__pyx_k_text), 0, 0, 1, 1},
-  {&__pyx_n_s_times, __pyx_k_times, sizeof(__pyx_k_times), 0, 0, 1, 1},
-  {&__pyx_n_s_title, __pyx_k_title, sizeof(__pyx_k_title), 0, 0, 1, 1},
-  {&__pyx_n_s_to_final, __pyx_k_to_final, sizeof(__pyx_k_to_final), 0, 0, 1, 1},
-  {&__pyx_n_s_to_string, __pyx_k_to_string, sizeof(__pyx_k_to_string), 0, 0, 1, 1},
-  {&__pyx_n_s_type, __pyx_k_type, sizeof(__pyx_k_type), 0, 0, 1, 1},
-  {&__pyx_n_b_uniform, __pyx_k_uniform, sizeof(__pyx_k_uniform), 0, 0, 0, 1},
-  {&__pyx_n_s_unique, __pyx_k_unique, sizeof(__pyx_k_unique), 0, 0, 1, 1},
-  {&__pyx_n_s_unknown_isymbol, __pyx_k_unknown_isymbol, sizeof(__pyx_k_unknown_isymbol), 0, 0, 1, 1},
-  {&__pyx_n_s_unknown_osymbol, __pyx_k_unknown_osymbol, sizeof(__pyx_k_unknown_osymbol), 0, 0, 1, 1},
-  {&__pyx_kp_b_unspecified, __pyx_k_unspecified, sizeof(__pyx_k_unspecified), 0, 0, 0, 0},
-  {&__pyx_n_s_utf8, __pyx_k_utf8, sizeof(__pyx_k_utf8), 0, 0, 1, 1},
-  {&__pyx_n_s_value, __pyx_k_value, sizeof(__pyx_k_value), 0, 0, 1, 1},
-  {&__pyx_n_b_vector, __pyx_k_vector, sizeof(__pyx_k_vector), 0, 0, 0, 1},
-  {&__pyx_n_s_verify, __pyx_k_verify, sizeof(__pyx_k_verify), 0, 0, 1, 1},
-  {&__pyx_n_s_vertical, __pyx_k_vertical, sizeof(__pyx_k_vertical), 0, 0, 1, 1},
-  {&__pyx_n_s_w, __pyx_k_w, sizeof(__pyx_k_w), 0, 0, 1, 1},
-  {&__pyx_n_s_warning, __pyx_k_warning, sizeof(__pyx_k_warning), 0, 0, 1, 1},
-  {&__pyx_n_s_weight, __pyx_k_weight, sizeof(__pyx_k_weight), 0, 0, 1, 1},
-  {&__pyx_n_s_weight_type, __pyx_k_weight_type, sizeof(__pyx_k_weight_type), 0, 0, 1, 1},
-  {&__pyx_n_s_weighted, __pyx_k_weighted, sizeof(__pyx_k_weighted), 0, 0, 1, 1},
-  {&__pyx_n_s_width, __pyx_k_width, sizeof(__pyx_k_width), 0, 0, 1, 1},
-  {&__pyx_n_s_write, __pyx_k_write, sizeof(__pyx_k_write), 0, 0, 1, 1},
-  {&__pyx_n_s_write_text, __pyx_k_write_text, sizeof(__pyx_k_write_text), 0, 0, 1, 1},
-  {&__pyx_n_s_write_to_string, __pyx_k_write_to_string, sizeof(__pyx_k_write_to_string), 0, 0, 1, 1},
-  {0, 0, 0, 0, 0, 0, 0}
-};
-static int __Pyx_InitCachedBuiltins(void) {
-  __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(0, 126, __pyx_L1_error)
-  __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) __PYX_ERR(0, 136, __pyx_L1_error)
-  __pyx_builtin_IndexError = __Pyx_GetBuiltinName(__pyx_n_s_IndexError); if (!__pyx_builtin_IndexError) __PYX_ERR(0, 141, __pyx_L1_error)
-  __pyx_builtin_IOError = __Pyx_GetBuiltinName(__pyx_n_s_IOError); if (!__pyx_builtin_IOError) __PYX_ERR(0, 146, __pyx_L1_error)
-  __pyx_builtin_object = __Pyx_GetBuiltinName(__pyx_n_s_object); if (!__pyx_builtin_object) __PYX_ERR(0, 2742, __pyx_L1_error)
-  __pyx_builtin_staticmethod = __Pyx_GetBuiltinName(__pyx_n_s_staticmethod); if (!__pyx_builtin_staticmethod) __PYX_ERR(0, 2762, __pyx_L1_error)
-  __pyx_builtin_id = __Pyx_GetBuiltinName(__pyx_n_s_id); if (!__pyx_builtin_id) __PYX_ERR(0, 370, __pyx_L1_error)
-  __pyx_builtin_TypeError = __Pyx_GetBuiltinName(__pyx_n_s_TypeError); if (!__pyx_builtin_TypeError) __PYX_ERR(1, 2, __pyx_L1_error)
-  __pyx_builtin_StopIteration = __Pyx_GetBuiltinName(__pyx_n_s_StopIteration); if (!__pyx_builtin_StopIteration) __PYX_ERR(0, 1145, __pyx_L1_error)
-  __pyx_builtin_KeyError = __Pyx_GetBuiltinName(__pyx_n_s_KeyError); if (!__pyx_builtin_KeyError) __PYX_ERR(0, 4358, __pyx_L1_error)
-  return 0;
-  __pyx_L1_error:;
-  return -1;
-}
-
-static int __Pyx_InitCachedConstants(void) {
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
-
-  /* "pywrapfst.pyx":388
- *   cdef void _check_weight(self) except *:
- *     if self.type() == b"none":
- *       raise FstArgError("Weight type not found")             # <<<<<<<<<<<<<<
- *     if self.to_string() == b"BadNumber":
- *       raise FstBadWeightError("Invalid weight")
- */
-  __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_Weight_type_not_found); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 388, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple_);
-  __Pyx_GIVEREF(__pyx_tuple_);
-
-  /* "pywrapfst.pyx":390
- *       raise FstArgError("Weight type not found")
- *     if self.to_string() == b"BadNumber":
- *       raise FstBadWeightError("Invalid weight")             # <<<<<<<<<<<<<<
- * 
- *   cpdef Weight copy(self):
- */
-  __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_s_Invalid_weight); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(0, 390, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__2);
-  __Pyx_GIVEREF(__pyx_tuple__2);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._weight cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._weight cannot be converted to a Python object for pickling")
- */
-  __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_s_self__weight_cannot_be_converted); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__3);
-  __Pyx_GIVEREF(__pyx_tuple__3);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._weight cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._weight cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_s_self__weight_cannot_be_converted); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__4);
-  __Pyx_GIVEREF(__pyx_tuple__4);
-
-  /* "pywrapfst.pyx":638
- *       tostring(weight_type))))
- *   if result._weight.get().Type() == b"none":
- *     raise FstArgError("Weight type not found")             # <<<<<<<<<<<<<<
- *   return result
- * 
- */
-  __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_s_Weight_type_not_found); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(0, 638, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__5);
-  __Pyx_GIVEREF(__pyx_tuple__5);
-
-  /* "pywrapfst.pyx":647
- *         fst.WeightClass.One(tostring(weight_type))))
- *   if result._weight.get().Type() == b"none":
- *     raise FstArgError("Weight type not found")             # <<<<<<<<<<<<<<
- *   return result
- * 
- */
-  __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_s_Weight_type_not_found); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 647, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__6);
-  __Pyx_GIVEREF(__pyx_tuple__6);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_s_self__table_cannot_be_converted); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__7);
-  __Pyx_GIVEREF(__pyx_tuple__7);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_tuple__8 = PyTuple_Pack(1, __pyx_kp_s_self__table_cannot_be_converted); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__8);
-  __Pyx_GIVEREF(__pyx_tuple__8);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_tuple__9 = PyTuple_Pack(1, __pyx_kp_s_self__encoder_self__table_cannot); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__9);
-  __Pyx_GIVEREF(__pyx_tuple__9);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._encoder,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_tuple__10 = PyTuple_Pack(1, __pyx_kp_s_self__encoder_self__table_cannot); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__10);
-  __Pyx_GIVEREF(__pyx_tuple__10);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_tuple__11 = PyTuple_Pack(1, __pyx_kp_s_self__fst_self__table_cannot_be); if (unlikely(!__pyx_tuple__11)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__11);
-  __Pyx_GIVEREF(__pyx_tuple__11);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._fst,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_tuple__12 = PyTuple_Pack(1, __pyx_kp_s_self__fst_self__table_cannot_be); if (unlikely(!__pyx_tuple__12)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__12);
-  __Pyx_GIVEREF(__pyx_tuple__12);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_tuple__14 = PyTuple_Pack(1, __pyx_kp_s_self__table_cannot_be_converted); if (unlikely(!__pyx_tuple__14)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__14);
-  __Pyx_GIVEREF(__pyx_tuple__14);
-
-  /* "(tree fragment)":4
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_tuple__15 = PyTuple_Pack(1, __pyx_kp_s_self__table_cannot_be_converted); if (unlikely(!__pyx_tuple__15)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__15);
-  __Pyx_GIVEREF(__pyx_tuple__15);
-
-  /* "(tree fragment)":2
- * def __reduce_cython__(self):
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- */
-  __pyx_tuple__16 = PyTuple_Pack(1, __pyx_kp_s_self__mfst_self__table_cannot_be); if (unlikely(!__pyx_tuple__16)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__16);
-  __Pyx_GIVEREF(__pyx_tuple__16);
+  {&__pyx_kp_s_self__writer_cannot_be_converted, __pyx_k_self__writer_cannot_be_converted, sizeof(__pyx_k_self__writer_cannot_be_converted), 0, 0, 1, 0},
+  {&__pyx_n_s_set_flags, __pyx_k_set_flags, sizeof(__pyx_k_set_flags), 0, 0, 1, 1},
+  {&__pyx_n_s_set_input_symbols, __pyx_k_set_input_symbols, sizeof(__pyx_k_set_input_symbols), 0, 0, 1, 1},
+  {&__pyx_n_s_set_name, __pyx_k_set_name, sizeof(__pyx_k_set_name), 0, 0, 1, 1},
+  {&__pyx_n_s_set_output_symbols, __pyx_k_set_output_symbols, sizeof(__pyx_k_set_output_symbols), 0, 0, 1, 1},
+  {&__pyx_n_s_set_value, __pyx_k_set_value, sizeof(__pyx_k_set_value), 0, 0, 1, 1},
+  {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1},
+  {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1},
+  {&__pyx_n_s_shortestdistance, __pyx_k_shortestdistance, sizeof(__pyx_k_shortestdistance), 0, 0, 1, 1},
+  {&__pyx_n_s_show_weight_one, __pyx_k_show_weight_one, sizeof(__pyx_k_show_weight_one), 0, 0, 1, 1},
+  {&__pyx_n_s_sort_type, __pyx_k_sort_type, sizeof(__pyx_k_sort_type), 0, 0, 1, 1},
+  {&__pyx_n_s_ssymbols, __pyx_k_ssymbols, sizeof(__pyx_k_ssymbols), 0, 0, 1, 1},
+  {&__pyx_n_b_standard, __pyx_k_standard, sizeof(__pyx_k_standard), 0, 0, 0, 1},
+  {&__pyx_n_s_start, __pyx_k_start, sizeof(__pyx_k_start), 0, 0, 1, 1},
+  {&__pyx_n_s_state, __pyx_k_state, sizeof(__pyx_k_state), 0, 0, 1, 1},
+  {&__pyx_n_s_states, __pyx_k_states, sizeof(__pyx_k_states), 0, 0, 1, 1},
+  {&__pyx_n_s_staticmethod, __pyx_k_staticmethod, sizeof(__pyx_k_staticmethod), 0, 0, 1, 1},
+  {&__pyx_n_s_stdin, __pyx_k_stdin, sizeof(__pyx_k_stdin), 0, 0, 1, 1},
+  {&__pyx_n_s_stdout, __pyx_k_stdout, sizeof(__pyx_k_stdout), 0, 0, 1, 1},
+  {&__pyx_n_s_subprocess, __pyx_k_subprocess, sizeof(__pyx_k_subprocess), 0, 0, 1, 1},
+  {&__pyx_n_s_subsequential_label, __pyx_k_subsequential_label, sizeof(__pyx_k_subsequential_label), 0, 0, 1, 1},
+  {&__pyx_n_s_symbol, __pyx_k_symbol, sizeof(__pyx_k_symbol), 0, 0, 1, 1},
+  {&__pyx_n_s_syms, __pyx_k_syms, sizeof(__pyx_k_syms), 0, 0, 1, 1},
+  {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1},
+  {&__pyx_n_s_test_2, __pyx_k_test_2, sizeof(__pyx_k_test_2), 0, 0, 1, 1},
+  {&__pyx_n_s_text, __pyx_k_text, sizeof(__pyx_k_text), 0, 0, 1, 1},
+  {&__pyx_n_s_times, __pyx_k_times, sizeof(__pyx_k_times), 0, 0, 1, 1},
+  {&__pyx_n_s_title, __pyx_k_title, sizeof(__pyx_k_title), 0, 0, 1, 1},
+  {&__pyx_n_s_to_final, __pyx_k_to_final, sizeof(__pyx_k_to_final), 0, 0, 1, 1},
+  {&__pyx_n_s_to_string, __pyx_k_to_string, sizeof(__pyx_k_to_string), 0, 0, 1, 1},
+  {&__pyx_n_s_type, __pyx_k_type, sizeof(__pyx_k_type), 0, 0, 1, 1},
+  {&__pyx_n_b_uniform, __pyx_k_uniform, sizeof(__pyx_k_uniform), 0, 0, 0, 1},
+  {&__pyx_n_s_unique, __pyx_k_unique, sizeof(__pyx_k_unique), 0, 0, 1, 1},
+  {&__pyx_n_s_unknown_isymbol, __pyx_k_unknown_isymbol, sizeof(__pyx_k_unknown_isymbol), 0, 0, 1, 1},
+  {&__pyx_n_s_unknown_osymbol, __pyx_k_unknown_osymbol, sizeof(__pyx_k_unknown_osymbol), 0, 0, 1, 1},
+  {&__pyx_kp_u_unspecified, __pyx_k_unspecified, sizeof(__pyx_k_unspecified), 0, 1, 0, 0},
+  {&__pyx_n_u_utf8, __pyx_k_utf8, sizeof(__pyx_k_utf8), 0, 1, 0, 1},
+  {&__pyx_n_s_value, __pyx_k_value, sizeof(__pyx_k_value), 0, 0, 1, 1},
+  {&__pyx_n_b_vector, __pyx_k_vector, sizeof(__pyx_k_vector), 0, 0, 0, 1},
+  {&__pyx_n_s_verify, __pyx_k_verify, sizeof(__pyx_k_verify), 0, 0, 1, 1},
+  {&__pyx_n_s_vertical, __pyx_k_vertical, sizeof(__pyx_k_vertical), 0, 0, 1, 1},
+  {&__pyx_n_s_w, __pyx_k_w, sizeof(__pyx_k_w), 0, 0, 1, 1},
+  {&__pyx_n_s_warning, __pyx_k_warning, sizeof(__pyx_k_warning), 0, 0, 1, 1},
+  {&__pyx_n_s_weight, __pyx_k_weight, sizeof(__pyx_k_weight), 0, 0, 1, 1},
+  {&__pyx_n_s_weight_type, __pyx_k_weight_type, sizeof(__pyx_k_weight_type), 0, 0, 1, 1},
+  {&__pyx_n_s_weighted, __pyx_k_weighted, sizeof(__pyx_k_weighted), 0, 0, 1, 1},
+  {&__pyx_n_s_width, __pyx_k_width, sizeof(__pyx_k_width), 0, 0, 1, 1},
+  {&__pyx_n_s_write, __pyx_k_write, sizeof(__pyx_k_write), 0, 0, 1, 1},
+  {&__pyx_n_s_write_text, __pyx_k_write_text, sizeof(__pyx_k_write_text), 0, 0, 1, 1},
+  {&__pyx_n_s_write_to_string, __pyx_k_write_to_string, sizeof(__pyx_k_write_to_string), 0, 0, 1, 1},
+  {0, 0, 0, 0, 0, 0, 0}
+};
+static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) {
+  __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(0, 111, __pyx_L1_error)
+  __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) __PYX_ERR(0, 121, __pyx_L1_error)
+  __pyx_builtin_IndexError = __Pyx_GetBuiltinName(__pyx_n_s_IndexError); if (!__pyx_builtin_IndexError) __PYX_ERR(0, 126, __pyx_L1_error)
+  __pyx_builtin_IOError = __Pyx_GetBuiltinName(__pyx_n_s_IOError); if (!__pyx_builtin_IOError) __PYX_ERR(0, 131, __pyx_L1_error)
+  __pyx_builtin_object = __Pyx_GetBuiltinName(__pyx_n_s_object); if (!__pyx_builtin_object) __PYX_ERR(0, 2762, __pyx_L1_error)
+  __pyx_builtin_staticmethod = __Pyx_GetBuiltinName(__pyx_n_s_staticmethod); if (!__pyx_builtin_staticmethod) __PYX_ERR(0, 2782, __pyx_L1_error)
+  __pyx_builtin_id = __Pyx_GetBuiltinName(__pyx_n_s_id); if (!__pyx_builtin_id) __PYX_ERR(0, 355, __pyx_L1_error)
+  __pyx_builtin_TypeError = __Pyx_GetBuiltinName(__pyx_n_s_TypeError); if (!__pyx_builtin_TypeError) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_builtin_StopIteration = __Pyx_GetBuiltinName(__pyx_n_s_StopIteration); if (!__pyx_builtin_StopIteration) __PYX_ERR(0, 1166, __pyx_L1_error)
+  __pyx_builtin_KeyError = __Pyx_GetBuiltinName(__pyx_n_s_KeyError); if (!__pyx_builtin_KeyError) __PYX_ERR(0, 4380, __pyx_L1_error)
+  return 0;
+  __pyx_L1_error:;
+  return -1;
+}
 
-  /* "(tree fragment)":4
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")
- * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._mfst,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
- */
-  __pyx_tuple__17 = PyTuple_Pack(1, __pyx_kp_s_self__mfst_self__table_cannot_be); if (unlikely(!__pyx_tuple__17)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__17);
-  __Pyx_GIVEREF(__pyx_tuple__17);
+static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
+ *     raise TypeError("self._weight cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
+ *     raise TypeError("self._weight cannot be converted to a Python object for pickling")
  */
-  __pyx_tuple__18 = PyTuple_Pack(1, __pyx_kp_s_self__smart_table_self__table_ca); if (unlikely(!__pyx_tuple__18)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__18);
-  __Pyx_GIVEREF(__pyx_tuple__18);
+  __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_self__weight_cannot_be_converted); if (unlikely(!__pyx_tuple_)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple_);
+  __Pyx_GIVEREF(__pyx_tuple_);
 
   /* "(tree fragment)":4
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")
+ *     raise TypeError("self._weight cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("self._smart_table,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
+ *     raise TypeError("self._weight cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__19 = PyTuple_Pack(1, __pyx_kp_s_self__smart_table_self__table_ca); if (unlikely(!__pyx_tuple__19)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__19);
-  __Pyx_GIVEREF(__pyx_tuple__19);
+  __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_s_self__weight_cannot_be_converted); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__2);
+  __Pyx_GIVEREF(__pyx_tuple__2);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
@@ -49927,18 +48638,18 @@ static int __Pyx_InitCachedConstants(void) {
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._siter,self._table cannot be converted to a Python object for pickling")
  */
-  __pyx_tuple__20 = PyTuple_Pack(1, __pyx_kp_s_self__siter_self__table_cannot_b); if (unlikely(!__pyx_tuple__20)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__20);
-  __Pyx_GIVEREF(__pyx_tuple__20);
+  __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_s_self__siter_self__table_cannot_b); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__4);
+  __Pyx_GIVEREF(__pyx_tuple__4);
 
   /* "(tree fragment)":4
  *     raise TypeError("self._siter,self._table cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._siter,self._table cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__21 = PyTuple_Pack(1, __pyx_kp_s_self__siter_self__table_cannot_b); if (unlikely(!__pyx_tuple__21)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__21);
-  __Pyx_GIVEREF(__pyx_tuple__21);
+  __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_s_self__siter_self__table_cannot_b); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__5);
+  __Pyx_GIVEREF(__pyx_tuple__5);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
@@ -49946,238 +48657,32 @@ static int __Pyx_InitCachedConstants(void) {
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._encoder cannot be converted to a Python object for pickling")
  */
-  __pyx_tuple__22 = PyTuple_Pack(1, __pyx_kp_s_self__encoder_cannot_be_converte); if (unlikely(!__pyx_tuple__22)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__22);
-  __Pyx_GIVEREF(__pyx_tuple__22);
+  __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_s_self__encoder_cannot_be_converte); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__6);
+  __Pyx_GIVEREF(__pyx_tuple__6);
 
   /* "(tree fragment)":4
  *     raise TypeError("self._encoder cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._encoder cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__23 = PyTuple_Pack(1, __pyx_kp_s_self__encoder_cannot_be_converte); if (unlikely(!__pyx_tuple__23)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__23);
-  __Pyx_GIVEREF(__pyx_tuple__23);
-
-  /* "pywrapfst.pyx":1400
- *     if proc.returncode != 0:  # Just to be explicit.
- *       raise subprocess.CalledProcessError(proc.returncode, self._DOT_TSVG)
- *     return sout.decode("utf8")             # <<<<<<<<<<<<<<
- * 
- *   def __repr__(self):
- */
-  __pyx_tuple__25 = PyTuple_Pack(1, __pyx_n_s_utf8); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(0, 1400, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__25);
-  __Pyx_GIVEREF(__pyx_tuple__25);
-
-  /* "pywrapfst.pyx":1576
- *     cdef size_t result = self._fst.get().NumArcs(state)
- *     if result == SIZE_MAX:
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     return result
- * 
- */
-  __pyx_tuple__26 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__26)) __PYX_ERR(0, 1576, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__26);
-  __Pyx_GIVEREF(__pyx_tuple__26);
-
-  /* "pywrapfst.pyx":1598
- *     cdef size_t result = self._fst.get().NumInputEpsilons(state)
- *     if result == SIZE_MAX:
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     return result
- * 
- */
-  __pyx_tuple__27 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__27)) __PYX_ERR(0, 1598, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__27);
-  __Pyx_GIVEREF(__pyx_tuple__27);
-
-  /* "pywrapfst.pyx":1620
- *     cdef size_t result = self._fst.get().NumOutputEpsilons(state)
- *     if result == SIZE_MAX:
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     return result
- * 
- */
-  __pyx_tuple__28 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__28)) __PYX_ERR(0, 1620, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__28);
-  __Pyx_GIVEREF(__pyx_tuple__28);
-
-  /* "pywrapfst.pyx":1770
- *     cdef stringstream sstrm
- *     if not self._fst.get().Write(sstrm, "write_to_string"):
- *       raise FstIOError("Write to string failed")             # <<<<<<<<<<<<<<
- *     return sstrm.str()
- * 
- */
-  __pyx_tuple__29 = PyTuple_Pack(1, __pyx_kp_s_Write_to_string_failed); if (unlikely(!__pyx_tuple__29)) __PYX_ERR(0, 1770, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__29);
-  __Pyx_GIVEREF(__pyx_tuple__29);
-
-  /* "pywrapfst.pyx":1790
- *     """
- *     if self._fst.get().Properties(fst.kError, True) == fst.kError:
- *       raise FstOpError("Operation failed")             # <<<<<<<<<<<<<<
- * 
- *   cdef void _add_arc(self, int64 state, Arc arc) except *:
- */
-  __pyx_tuple__30 = PyTuple_Pack(1, __pyx_kp_s_Operation_failed); if (unlikely(!__pyx_tuple__30)) __PYX_ERR(0, 1790, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__30);
-  __Pyx_GIVEREF(__pyx_tuple__30);
-
-  /* "pywrapfst.pyx":1794
- *   cdef void _add_arc(self, int64 state, Arc arc) except *:
- *     if not self._fst.get().ValidStateId(state):
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     if not self._mfst.get().AddArc(state, deref(arc._arc)):
- *       raise FstOpError("Incompatible or invalid weight type")
- */
-  __pyx_tuple__31 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__31)) __PYX_ERR(0, 1794, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__31);
-  __Pyx_GIVEREF(__pyx_tuple__31);
-
-  /* "pywrapfst.pyx":1796
- *       raise FstIndexError("State index out of range")
- *     if not self._mfst.get().AddArc(state, deref(arc._arc)):
- *       raise FstOpError("Incompatible or invalid weight type")             # <<<<<<<<<<<<<<
- *     self._check_mutating_imethod()
- * 
- */
-  __pyx_tuple__32 = PyTuple_Pack(1, __pyx_kp_s_Incompatible_or_invalid_weight_t); if (unlikely(!__pyx_tuple__32)) __PYX_ERR(0, 1796, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__32);
-  __Pyx_GIVEREF(__pyx_tuple__32);
-
-  /* "pywrapfst.pyx":1961
- *     if not (self._mfst.get().DeleteArcs(state, n) if n else
- *             self._mfst.get().DeleteArcs(state)):
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     self._check_mutating_imethod()
- * 
- */
-  __pyx_tuple__33 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__33)) __PYX_ERR(0, 1961, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__33);
-  __Pyx_GIVEREF(__pyx_tuple__33);
-
-  /* "pywrapfst.pyx":1991
- *     if states:
- *       if not self._mfst.get().DeleteStates(<const vector[int64]> states):
- *         raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     else:
- *       self._mfst.get().DeleteStates()
- */
-  __pyx_tuple__34 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__34)) __PYX_ERR(0, 1991, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__34);
-  __Pyx_GIVEREF(__pyx_tuple__34);
-
-  /* "pywrapfst.pyx":2260
- *         _opairs.get().push_back(fst.LabelPair(before, after))
- *     if _ipairs.get().empty() and _opairs.get().empty():
- *       raise FstArgError("No relabeling pairs specified.")             # <<<<<<<<<<<<<<
- *     fst.Relabel(self._mfst.get(), deref(_ipairs), deref(_opairs))
- *     self._check_mutating_imethod()
- */
-  __pyx_tuple__43 = PyTuple_Pack(1, __pyx_kp_s_No_relabeling_pairs_specified); if (unlikely(!__pyx_tuple__43)) __PYX_ERR(0, 2260, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__43);
-  __Pyx_GIVEREF(__pyx_tuple__43);
-
-  /* "pywrapfst.pyx":2299
- *                             bool attach_new_osymbols=True) except *:
- *     if new_isymbols is None and new_osymbols is None:
- *       raise FstArgError("No new SymbolTables specified")             # <<<<<<<<<<<<<<
- *     cdef fst.SymbolTable *new_isymbols_ptr = NULL
- *     if new_isymbols is not None:
- */
-  __pyx_tuple__44 = PyTuple_Pack(1, __pyx_kp_s_No_new_SymbolTables_specified); if (unlikely(!__pyx_tuple__44)) __PYX_ERR(0, 2299, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__44);
-  __Pyx_GIVEREF(__pyx_tuple__44);
-
-  /* "pywrapfst.pyx":2367
- *   cdef void _reserve_arcs(self, int64 state, size_t n) except *:
- *     if not self._mfst.get().ReserveArcs(state, n):
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     self._check_mutating_imethod()
- * 
- */
-  __pyx_tuple__45 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__45)) __PYX_ERR(0, 2367, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__45);
-  __Pyx_GIVEREF(__pyx_tuple__45);
-
-  /* "pywrapfst.pyx":2494
- *   cdef void _set_final(self, int64 state, weight=None) except *:
- *     if not self._mfst.get().ValidStateId(state):
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     cdef fst.WeightClass wc = _get_WeightClass_or_One(self.weight_type(),
- *                                                       weight)
- */
-  __pyx_tuple__50 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__50)) __PYX_ERR(0, 2494, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__50);
-  __Pyx_GIVEREF(__pyx_tuple__50);
-
-  /* "pywrapfst.pyx":2498
- *                                                       weight)
- *     if not self._mfst.get().SetFinal(state, wc):
- *       raise FstOpError("Incompatible or invalid weight")             # <<<<<<<<<<<<<<
- *     self._check_mutating_imethod()
- * 
- */
-  __pyx_tuple__51 = PyTuple_Pack(1, __pyx_kp_s_Incompatible_or_invalid_weight); if (unlikely(!__pyx_tuple__51)) __PYX_ERR(0, 2498, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__51);
-  __Pyx_GIVEREF(__pyx_tuple__51);
-
-  /* "pywrapfst.pyx":2598
- *   cdef void _set_start(self, int64 state) except *:
- *     if not self._mfst.get().SetStart(state):
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     self._check_mutating_imethod()
- * 
- */
-  __pyx_tuple__52 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__52)) __PYX_ERR(0, 2598, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__52);
-  __Pyx_GIVEREF(__pyx_tuple__52);
-
-  /* "pywrapfst.pyx":2624
- *     # TopSort returns False if the FST is cyclic, and thus can't be TopSorted.
- *     if not fst.TopSort(self._mfst.get()):
- *       logging.warning("Cannot topsort cyclic FST.")             # <<<<<<<<<<<<<<
- *     self._check_mutating_imethod()
- * 
- */
-  __pyx_tuple__53 = PyTuple_Pack(1, __pyx_kp_s_Cannot_topsort_cyclic_FST); if (unlikely(!__pyx_tuple__53)) __PYX_ERR(0, 2624, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__53);
-  __Pyx_GIVEREF(__pyx_tuple__53);
-
-  /* "pywrapfst.pyx":2693
- * cdef _Fst _init_Fst(FstClass_ptr tfst):
- *   if tfst.Properties(fst.kError, True):
- *     raise FstOpError("Operation failed")             # <<<<<<<<<<<<<<
- *   cdef _Fst ofst = _Fst.__new__(_Fst)
- *   ofst._fst.reset(tfst)
- */
-  __pyx_tuple__54 = PyTuple_Pack(1, __pyx_kp_s_Operation_failed); if (unlikely(!__pyx_tuple__54)) __PYX_ERR(0, 2693, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__54);
-  __Pyx_GIVEREF(__pyx_tuple__54);
-
-  /* "pywrapfst.pyx":2701
- * cdef _MutableFst _init_MutableFst(MutableFstClass_ptr tfst):
- *   if tfst.Properties(fst.kError, True):
- *     raise FstOpError("Operation failed")             # <<<<<<<<<<<<<<
- *   cdef _MutableFst ofst = _MutableFst.__new__(_MutableFst)
- *   ofst._fst.reset(tfst)
- */
-  __pyx_tuple__55 = PyTuple_Pack(1, __pyx_kp_s_Operation_failed); if (unlikely(!__pyx_tuple__55)) __PYX_ERR(0, 2701, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__55);
-  __Pyx_GIVEREF(__pyx_tuple__55);
+  __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_s_self__encoder_cannot_be_converte); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__7);
+  __Pyx_GIVEREF(__pyx_tuple__7);
 
-  /* "pywrapfst.pyx":2738
- *   tfst.reset(fst.FstClass.ReadFromStream(sstrm, b"<pywrapfst>"))
- *   if tfst.get() == NULL:
- *     raise FstIOError("Read failed: <string>")             # <<<<<<<<<<<<<<
- *   return _init_XFst(tfst.release())
- * 
+  /* "pywrapfst.pyx":1398
+ *   @staticmethod
+ *   cdef string _local_render_svg(const string &dot):
+ *     proc = subprocess.Popen(("dot", "-Tsvg"),             # <<<<<<<<<<<<<<
+ *                             stdin=subprocess.PIPE,
+ *                             stdout=subprocess.PIPE)
  */
-  __pyx_tuple__56 = PyTuple_Pack(1, __pyx_kp_s_Read_failed_string); if (unlikely(!__pyx_tuple__56)) __PYX_ERR(0, 2738, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__56);
-  __Pyx_GIVEREF(__pyx_tuple__56);
+  __pyx_tuple__8 = PyTuple_Pack(2, __pyx_n_u_dot, __pyx_kp_u_Tsvg); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 1398, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__8);
+  __Pyx_GIVEREF(__pyx_tuple__8);
+  __pyx_tuple__9 = PyTuple_Pack(1, __pyx_tuple__8); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(0, 1398, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__9);
+  __Pyx_GIVEREF(__pyx_tuple__9);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
@@ -50185,29 +48690,18 @@ static int __Pyx_InitCachedConstants(void) {
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._arc cannot be converted to a Python object for pickling")
  */
-  __pyx_tuple__57 = PyTuple_Pack(1, __pyx_kp_s_self__arc_cannot_be_converted_to); if (unlikely(!__pyx_tuple__57)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__57);
-  __Pyx_GIVEREF(__pyx_tuple__57);
+  __pyx_tuple__23 = PyTuple_Pack(1, __pyx_kp_s_self__arc_cannot_be_converted_to); if (unlikely(!__pyx_tuple__23)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__23);
+  __Pyx_GIVEREF(__pyx_tuple__23);
 
   /* "(tree fragment)":4
  *     raise TypeError("self._arc cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._arc cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__58 = PyTuple_Pack(1, __pyx_kp_s_self__arc_cannot_be_converted_to); if (unlikely(!__pyx_tuple__58)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__58);
-  __Pyx_GIVEREF(__pyx_tuple__58);
-
-  /* "pywrapfst.pyx":2978
- *   def __init__(self, _Fst ifst, int64 state):
- *     if not ifst._fst.get().ValidStateId(state):
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
- *     self._fst = ifst._fst
- */
-  __pyx_tuple__59 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__59)) __PYX_ERR(0, 2978, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__59);
-  __Pyx_GIVEREF(__pyx_tuple__59);
+  __pyx_tuple__24 = PyTuple_Pack(1, __pyx_kp_s_self__arc_cannot_be_converted_to); if (unlikely(!__pyx_tuple__24)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__24);
+  __Pyx_GIVEREF(__pyx_tuple__24);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
@@ -50215,29 +48709,18 @@ static int __Pyx_InitCachedConstants(void) {
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._aiter,self._fst cannot be converted to a Python object for pickling")
  */
-  __pyx_tuple__60 = PyTuple_Pack(1, __pyx_kp_s_self__aiter_self__fst_cannot_be); if (unlikely(!__pyx_tuple__60)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__60);
-  __Pyx_GIVEREF(__pyx_tuple__60);
+  __pyx_tuple__25 = PyTuple_Pack(1, __pyx_kp_s_self__aiter_self__fst_cannot_be); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__25);
+  __Pyx_GIVEREF(__pyx_tuple__25);
 
   /* "(tree fragment)":4
  *     raise TypeError("self._aiter,self._fst cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._aiter,self._fst cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__61 = PyTuple_Pack(1, __pyx_kp_s_self__aiter_self__fst_cannot_be); if (unlikely(!__pyx_tuple__61)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__61);
-  __Pyx_GIVEREF(__pyx_tuple__61);
-
-  /* "pywrapfst.pyx":3090
- *   def __init__(self, _MutableFst ifst, int64 state):
- *     if not ifst._fst.get().ValidStateId(state):
- *       raise FstIndexError("State index out of range")             # <<<<<<<<<<<<<<
- *     # Makes copy of the shared_ptr, potentially extending the FST's lifetime.
- *     self._mfst = ifst._mfst
- */
-  __pyx_tuple__62 = PyTuple_Pack(1, __pyx_kp_s_State_index_out_of_range); if (unlikely(!__pyx_tuple__62)) __PYX_ERR(0, 3090, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__62);
-  __Pyx_GIVEREF(__pyx_tuple__62);
+  __pyx_tuple__26 = PyTuple_Pack(1, __pyx_kp_s_self__aiter_self__fst_cannot_be); if (unlikely(!__pyx_tuple__26)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__26);
+  __Pyx_GIVEREF(__pyx_tuple__26);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
@@ -50245,18 +48728,18 @@ static int __Pyx_InitCachedConstants(void) {
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._aiter,self._mfst cannot be converted to a Python object for pickling")
  */
-  __pyx_tuple__63 = PyTuple_Pack(1, __pyx_kp_s_self__aiter_self__mfst_cannot_be); if (unlikely(!__pyx_tuple__63)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__63);
-  __Pyx_GIVEREF(__pyx_tuple__63);
+  __pyx_tuple__27 = PyTuple_Pack(1, __pyx_kp_s_self__aiter_self__mfst_cannot_be); if (unlikely(!__pyx_tuple__27)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__27);
+  __Pyx_GIVEREF(__pyx_tuple__27);
 
   /* "(tree fragment)":4
  *     raise TypeError("self._aiter,self._mfst cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._aiter,self._mfst cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__64 = PyTuple_Pack(1, __pyx_kp_s_self__aiter_self__mfst_cannot_be); if (unlikely(!__pyx_tuple__64)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__64);
-  __Pyx_GIVEREF(__pyx_tuple__64);
+  __pyx_tuple__28 = PyTuple_Pack(1, __pyx_kp_s_self__aiter_self__mfst_cannot_be); if (unlikely(!__pyx_tuple__28)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__28);
+  __Pyx_GIVEREF(__pyx_tuple__28);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
@@ -50264,29 +48747,18 @@ static int __Pyx_InitCachedConstants(void) {
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._fst,self._siter cannot be converted to a Python object for pickling")
  */
-  __pyx_tuple__65 = PyTuple_Pack(1, __pyx_kp_s_self__fst_self__siter_cannot_be); if (unlikely(!__pyx_tuple__65)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__65);
-  __Pyx_GIVEREF(__pyx_tuple__65);
+  __pyx_tuple__29 = PyTuple_Pack(1, __pyx_kp_s_self__fst_self__siter_cannot_be); if (unlikely(!__pyx_tuple__29)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__29);
+  __Pyx_GIVEREF(__pyx_tuple__29);
 
   /* "(tree fragment)":4
  *     raise TypeError("self._fst,self._siter cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._fst,self._siter cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__66 = PyTuple_Pack(1, __pyx_kp_s_self__fst_self__siter_cannot_be); if (unlikely(!__pyx_tuple__66)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__66);
-  __Pyx_GIVEREF(__pyx_tuple__66);
-
-  /* "pywrapfst.pyx":4190
- *     self._sstrm.reset(new stringstream())
- *     if tfst.get() == NULL:
- *       raise FstOpError("Compilation failed")             # <<<<<<<<<<<<<<
- *     return _init_XFst(tfst.release())
- * 
- */
-  __pyx_tuple__90 = PyTuple_Pack(1, __pyx_kp_s_Compilation_failed); if (unlikely(!__pyx_tuple__90)) __PYX_ERR(0, 4190, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__90);
-  __Pyx_GIVEREF(__pyx_tuple__90);
+  __pyx_tuple__30 = PyTuple_Pack(1, __pyx_kp_s_self__fst_self__siter_cannot_be); if (unlikely(!__pyx_tuple__30)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__30);
+  __Pyx_GIVEREF(__pyx_tuple__30);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
@@ -50294,18 +48766,18 @@ static int __Pyx_InitCachedConstants(void) {
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
  */
-  __pyx_tuple__91 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__91)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__91);
-  __Pyx_GIVEREF(__pyx_tuple__91);
+  __pyx_tuple__54 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__54)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__54);
+  __Pyx_GIVEREF(__pyx_tuple__54);
 
   /* "(tree fragment)":4
  *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__92 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__92)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__92);
-  __Pyx_GIVEREF(__pyx_tuple__92);
+  __pyx_tuple__55 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__55)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__55);
+  __Pyx_GIVEREF(__pyx_tuple__55);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
@@ -50313,40 +48785,18 @@ static int __Pyx_InitCachedConstants(void) {
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._reader cannot be converted to a Python object for pickling")
  */
-  __pyx_tuple__93 = PyTuple_Pack(1, __pyx_kp_s_self__reader_cannot_be_converted); if (unlikely(!__pyx_tuple__93)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__93);
-  __Pyx_GIVEREF(__pyx_tuple__93);
+  __pyx_tuple__56 = PyTuple_Pack(1, __pyx_kp_s_self__reader_cannot_be_converted); if (unlikely(!__pyx_tuple__56)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__56);
+  __Pyx_GIVEREF(__pyx_tuple__56);
 
   /* "(tree fragment)":4
  *     raise TypeError("self._reader cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._reader cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__94 = PyTuple_Pack(1, __pyx_kp_s_self__reader_cannot_be_converted); if (unlikely(!__pyx_tuple__94)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__94);
-  __Pyx_GIVEREF(__pyx_tuple__94);
-
-  /* "pywrapfst.pyx":4444
- *     # used by the FAR was initialized to use.
- *     if not self._writer.get().Add(tostring(key), deref(ifst._fst)):
- *       raise FstOpError("Incompatible or invalid arc type")             # <<<<<<<<<<<<<<
- *     # An error here usually indicates a key out of order.
- *     if self._writer.get().Error():
- */
-  __pyx_tuple__95 = PyTuple_Pack(1, __pyx_kp_s_Incompatible_or_invalid_arc_type); if (unlikely(!__pyx_tuple__95)) __PYX_ERR(0, 4444, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__95);
-  __Pyx_GIVEREF(__pyx_tuple__95);
-
-  /* "pywrapfst.pyx":4447
- *     # An error here usually indicates a key out of order.
- *     if self._writer.get().Error():
- *       raise FstArgError("Key out of order")             # <<<<<<<<<<<<<<
- * 
- *   cpdef string arc_type(self):
- */
-  __pyx_tuple__96 = PyTuple_Pack(1, __pyx_kp_s_Key_out_of_order); if (unlikely(!__pyx_tuple__96)) __PYX_ERR(0, 4447, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__96);
-  __Pyx_GIVEREF(__pyx_tuple__96);
+  __pyx_tuple__57 = PyTuple_Pack(1, __pyx_kp_s_self__reader_cannot_be_converted); if (unlikely(!__pyx_tuple__57)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__57);
+  __Pyx_GIVEREF(__pyx_tuple__57);
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
@@ -50354,137 +48804,128 @@ static int __Pyx_InitCachedConstants(void) {
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._writer cannot be converted to a Python object for pickling")
  */
-  __pyx_tuple__97 = PyTuple_Pack(1, __pyx_kp_s_self__writer_cannot_be_converted); if (unlikely(!__pyx_tuple__97)) __PYX_ERR(1, 2, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__97);
-  __Pyx_GIVEREF(__pyx_tuple__97);
+  __pyx_tuple__58 = PyTuple_Pack(1, __pyx_kp_s_self__writer_cannot_be_converted); if (unlikely(!__pyx_tuple__58)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__58);
+  __Pyx_GIVEREF(__pyx_tuple__58);
 
   /* "(tree fragment)":4
  *     raise TypeError("self._writer cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  *     raise TypeError("self._writer cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_tuple__98 = PyTuple_Pack(1, __pyx_kp_s_self__writer_cannot_be_converted); if (unlikely(!__pyx_tuple__98)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__98);
-  __Pyx_GIVEREF(__pyx_tuple__98);
+  __pyx_tuple__59 = PyTuple_Pack(1, __pyx_kp_s_self__writer_cannot_be_converted); if (unlikely(!__pyx_tuple__59)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__59);
+  __Pyx_GIVEREF(__pyx_tuple__59);
 
-  /* "pywrapfst.pyx":456
+  /* "pywrapfst.pyx":441
  * 
  * 
  * def plus(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
  *   """
  *   plus(lhs, rhs)
  */
-  __pyx_tuple__99 = PyTuple_Pack(3, __pyx_n_s_lhs, __pyx_n_s_rhs, __pyx_n_s_result); if (unlikely(!__pyx_tuple__99)) __PYX_ERR(0, 456, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__99);
-  __Pyx_GIVEREF(__pyx_tuple__99);
-  __pyx_codeobj__100 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__99, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_plus, 456, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__100)) __PYX_ERR(0, 456, __pyx_L1_error)
+  __pyx_tuple__60 = PyTuple_Pack(3, __pyx_n_s_lhs, __pyx_n_s_rhs, __pyx_n_s_result); if (unlikely(!__pyx_tuple__60)) __PYX_ERR(0, 441, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__60);
+  __Pyx_GIVEREF(__pyx_tuple__60);
+  __pyx_codeobj__61 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__60, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_plus, 441, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__61)) __PYX_ERR(0, 441, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":488
+  /* "pywrapfst.pyx":473
  * 
  * 
  * def times(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
  *   """
  *   times(lhs, rhs)
  */
-  __pyx_tuple__101 = PyTuple_Pack(3, __pyx_n_s_lhs, __pyx_n_s_rhs, __pyx_n_s_result); if (unlikely(!__pyx_tuple__101)) __PYX_ERR(0, 488, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__101);
-  __Pyx_GIVEREF(__pyx_tuple__101);
-  __pyx_codeobj__102 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__101, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_times, 488, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__102)) __PYX_ERR(0, 488, __pyx_L1_error)
+  __pyx_tuple__62 = PyTuple_Pack(3, __pyx_n_s_lhs, __pyx_n_s_rhs, __pyx_n_s_result); if (unlikely(!__pyx_tuple__62)) __PYX_ERR(0, 473, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__62);
+  __Pyx_GIVEREF(__pyx_tuple__62);
+  __pyx_codeobj__63 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__62, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_times, 473, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__63)) __PYX_ERR(0, 473, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":520
+  /* "pywrapfst.pyx":505
  * 
  * 
  * def divide(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
  *   """
  *   divide(lhs, rhs)
  */
-  __pyx_tuple__103 = PyTuple_Pack(3, __pyx_n_s_lhs, __pyx_n_s_rhs, __pyx_n_s_result); if (unlikely(!__pyx_tuple__103)) __PYX_ERR(0, 520, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__103);
-  __Pyx_GIVEREF(__pyx_tuple__103);
-  __pyx_codeobj__104 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__103, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_divide, 520, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__104)) __PYX_ERR(0, 520, __pyx_L1_error)
+  __pyx_tuple__64 = PyTuple_Pack(3, __pyx_n_s_lhs, __pyx_n_s_rhs, __pyx_n_s_result); if (unlikely(!__pyx_tuple__64)) __PYX_ERR(0, 505, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__64);
+  __Pyx_GIVEREF(__pyx_tuple__64);
+  __pyx_codeobj__65 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__64, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_divide, 505, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__65)) __PYX_ERR(0, 505, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":553
+  /* "pywrapfst.pyx":538
  * 
  * 
  * def power(Weight w, size_t n):             # <<<<<<<<<<<<<<
  *   """
  *   power(lhs, rhs)
  */
-  __pyx_tuple__105 = PyTuple_Pack(3, __pyx_n_s_w, __pyx_n_s_n, __pyx_n_s_result); if (unlikely(!__pyx_tuple__105)) __PYX_ERR(0, 553, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__105);
-  __Pyx_GIVEREF(__pyx_tuple__105);
-  __pyx_codeobj__106 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__105, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_power, 553, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__106)) __PYX_ERR(0, 553, __pyx_L1_error)
+  __pyx_tuple__66 = PyTuple_Pack(3, __pyx_n_s_w, __pyx_n_s_n, __pyx_n_s_result); if (unlikely(!__pyx_tuple__66)) __PYX_ERR(0, 538, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__66);
+  __Pyx_GIVEREF(__pyx_tuple__66);
+  __pyx_codeobj__67 = (PyObject*)__Pyx_PyCode_New(2, 0, 3, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__66, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_power, 538, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__67)) __PYX_ERR(0, 538, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2742
+  /* "pywrapfst.pyx":2762
  * 
  * 
  * class Fst(object):             # <<<<<<<<<<<<<<
  * 
  *    """
  */
-  __pyx_tuple__107 = PyTuple_Pack(1, __pyx_builtin_object); if (unlikely(!__pyx_tuple__107)) __PYX_ERR(0, 2742, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__107);
-  __Pyx_GIVEREF(__pyx_tuple__107);
+  __pyx_tuple__68 = PyTuple_Pack(1, __pyx_builtin_object); if (unlikely(!__pyx_tuple__68)) __PYX_ERR(0, 2762, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__68);
+  __Pyx_GIVEREF(__pyx_tuple__68);
 
-  /* "pywrapfst.pyx":2759
+  /* "pywrapfst.pyx":2779
  *    """
  * 
  *    def __new__(cls, arc_type=b"standard"):             # <<<<<<<<<<<<<<
  *     return _create_Fst(arc_type)
  * 
  */
-  __pyx_tuple__108 = PyTuple_Pack(2, __pyx_n_s_cls, __pyx_n_s_arc_type); if (unlikely(!__pyx_tuple__108)) __PYX_ERR(0, 2759, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__108);
-  __Pyx_GIVEREF(__pyx_tuple__108);
-  __pyx_codeobj__109 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__108, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_new, 2759, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__109)) __PYX_ERR(0, 2759, __pyx_L1_error)
-  __pyx_tuple__110 = PyTuple_Pack(1, ((PyObject*)__pyx_n_b_standard)); if (unlikely(!__pyx_tuple__110)) __PYX_ERR(0, 2759, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__110);
-  __Pyx_GIVEREF(__pyx_tuple__110);
+  __pyx_tuple__69 = PyTuple_Pack(2, __pyx_n_s_cls, __pyx_n_s_arc_type); if (unlikely(!__pyx_tuple__69)) __PYX_ERR(0, 2779, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__69);
+  __Pyx_GIVEREF(__pyx_tuple__69);
+  __pyx_codeobj__70 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__69, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_new, 2779, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__70)) __PYX_ERR(0, 2779, __pyx_L1_error)
+  __pyx_tuple__71 = PyTuple_Pack(1, ((PyObject*)__pyx_n_b_standard)); if (unlikely(!__pyx_tuple__71)) __PYX_ERR(0, 2779, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__71);
+  __Pyx_GIVEREF(__pyx_tuple__71);
 
-  /* "pywrapfst.pyx":2763
+  /* "pywrapfst.pyx":2783
  * 
  *    @staticmethod
  *    def read(filename):             # <<<<<<<<<<<<<<
  *      """
  *      read(filename):
  */
-  __pyx_tuple__111 = PyTuple_Pack(1, __pyx_n_s_filename); if (unlikely(!__pyx_tuple__111)) __PYX_ERR(0, 2763, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__111);
-  __Pyx_GIVEREF(__pyx_tuple__111);
-  __pyx_codeobj__112 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__111, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_read, 2763, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__112)) __PYX_ERR(0, 2763, __pyx_L1_error)
+  __pyx_tuple__72 = PyTuple_Pack(1, __pyx_n_s_filename); if (unlikely(!__pyx_tuple__72)) __PYX_ERR(0, 2783, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__72);
+  __Pyx_GIVEREF(__pyx_tuple__72);
+  __pyx_codeobj__73 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__72, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_read, 2783, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__73)) __PYX_ERR(0, 2783, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":2781
+  /* "pywrapfst.pyx":2801
  * 
  *    @staticmethod
  *    def read_from_string(state):             # <<<<<<<<<<<<<<
  *      """
  *      read_from_string(string, fst_type=None)
  */
-  __pyx_tuple__113 = PyTuple_Pack(1, __pyx_n_s_state); if (unlikely(!__pyx_tuple__113)) __PYX_ERR(0, 2781, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__113);
-  __Pyx_GIVEREF(__pyx_tuple__113);
-  __pyx_codeobj__114 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__113, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_read_from_string_2, 2781, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__114)) __PYX_ERR(0, 2781, __pyx_L1_error)
+  __pyx_tuple__74 = PyTuple_Pack(1, __pyx_n_s_state); if (unlikely(!__pyx_tuple__74)) __PYX_ERR(0, 2801, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__74);
+  __Pyx_GIVEREF(__pyx_tuple__74);
+  __pyx_codeobj__75 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__74, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_read_from_string, 2801, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__75)) __PYX_ERR(0, 2801, __pyx_L1_error)
 
-  /* "pywrapfst.pyx":3949
+  /* "pywrapfst.pyx":3967
  * 
  * 
  * def shortestdistance(_Fst ifst,             # <<<<<<<<<<<<<<
  *                      float delta=fst.kShortestDelta,
  *                      int64 nstate=fst.kNoStateId,
  */
-  __pyx_tuple__115 = PyTuple_Pack(8, __pyx_n_s_ifst, __pyx_n_s_delta, __pyx_n_s_nstate, __pyx_n_s_queue_type, __pyx_n_s_reverse, __pyx_n_s_distance, __pyx_n_s_weight_type, __pyx_n_s_weight); if (unlikely(!__pyx_tuple__115)) __PYX_ERR(0, 3949, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__115);
-  __Pyx_GIVEREF(__pyx_tuple__115);
-  __pyx_codeobj__116 = (PyObject*)__Pyx_PyCode_New(5, 0, 8, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__115, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_shortestdistance, 3949, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__116)) __PYX_ERR(0, 3949, __pyx_L1_error)
-
-  /* "pywrapfst.pyx":4493
- * 
- * @atexit.register
- * def _reset_fst_error_fatal():             # <<<<<<<<<<<<<<
- *   fst.FLAGS_fst_error_fatal = _fst_error_fatal_old
- * 
- */
-  __pyx_codeobj__117 = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_reset_fst_error_fatal, 4493, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__117)) __PYX_ERR(0, 4493, __pyx_L1_error)
+  __pyx_tuple__76 = PyTuple_Pack(8, __pyx_n_s_ifst, __pyx_n_s_delta, __pyx_n_s_nstate, __pyx_n_s_queue_type, __pyx_n_s_reverse, __pyx_n_s_distance, __pyx_n_s_weight_type, __pyx_n_s_weight); if (unlikely(!__pyx_tuple__76)) __PYX_ERR(0, 3967, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__76);
+  __Pyx_GIVEREF(__pyx_tuple__76);
+  __pyx_codeobj__77 = (PyObject*)__Pyx_PyCode_New(5, 0, 8, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__76, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pywrapfst_pyx, __pyx_n_s_shortestdistance, 3967, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__77)) __PYX_ERR(0, 3967, __pyx_L1_error)
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -50492,22 +48933,20 @@ static int __Pyx_InitCachedConstants(void) {
   return -1;
 }
 
-static int __Pyx_InitGlobals(void) {
+static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) {
   if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error);
-  __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) __PYX_ERR(0, 1, __pyx_L1_error)
-  __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error)
   return 0;
   __pyx_L1_error:;
   return -1;
 }
 
-static int __Pyx_modinit_global_init_code(void); /*proto*/
-static int __Pyx_modinit_variable_export_code(void); /*proto*/
-static int __Pyx_modinit_function_export_code(void); /*proto*/
-static int __Pyx_modinit_type_init_code(void); /*proto*/
-static int __Pyx_modinit_type_import_code(void); /*proto*/
-static int __Pyx_modinit_variable_import_code(void); /*proto*/
-static int __Pyx_modinit_function_import_code(void); /*proto*/
+static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/
+static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/
+static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/
+static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/
+static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/
+static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/
+static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/
 
 static int __Pyx_modinit_global_init_code(void) {
   __Pyx_RefNannyDeclarations
@@ -50549,12 +48988,13 @@ static int __Pyx_modinit_function_export_code(void) {
   if (__Pyx_ExportFunction("_init_FstSymbolTable", (void (*)(void))__pyx_f_9pywrapfst__init_FstSymbolTable, "struct __pyx_obj_9pywrapfst__FstSymbolTable *(fst::SymbolTable *, std::shared_ptr<fst::script::FstClass> )") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("_init_MutableFstSymbolTable", (void (*)(void))__pyx_f_9pywrapfst__init_MutableFstSymbolTable, "struct __pyx_obj_9pywrapfst__MutableFstSymbolTable *(fst::SymbolTable *, std::shared_ptr<fst::script::MutableFstClass> )") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("_init_SymbolTable", (void (*)(void))__pyx_f_9pywrapfst__init_SymbolTable, "struct __pyx_obj_9pywrapfst_SymbolTable *(fst::SymbolTable *)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
+  if (__Pyx_ExportFunction("_read_SymbolTable_from_string", (void (*)(void))__pyx_f_9pywrapfst__read_SymbolTable_from_string, "struct __pyx_obj_9pywrapfst_SymbolTable *(PyObject *, int __pyx_skip_dispatch)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("_init_Fst", (void (*)(void))__pyx_f_9pywrapfst__init_Fst, "struct __pyx_obj_9pywrapfst__Fst *(__pyx_t_9pywrapfst_FstClass_ptr)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("_init_MutableFst", (void (*)(void))__pyx_f_9pywrapfst__init_MutableFst, "struct __pyx_obj_9pywrapfst__MutableFst *(__pyx_t_9pywrapfst_MutableFstClass_ptr)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("_init_XFst", (void (*)(void))__pyx_f_9pywrapfst__init_XFst, "struct __pyx_obj_9pywrapfst__Fst *(__pyx_t_9pywrapfst_FstClass_ptr)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("_create_Fst", (void (*)(void))__pyx_f_9pywrapfst__create_Fst, "struct __pyx_obj_9pywrapfst__MutableFst *(struct __pyx_opt_args_9pywrapfst__create_Fst *__pyx_optional_args)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("_read", (void (*)(void))__pyx_f_9pywrapfst__read, "struct __pyx_obj_9pywrapfst__Fst *(PyObject *, int __pyx_skip_dispatch)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
-  if (__Pyx_ExportFunction("_read_from_string", (void (*)(void))__pyx_f_9pywrapfst__read_from_string, "struct __pyx_obj_9pywrapfst__Fst *(PyObject *, int __pyx_skip_dispatch)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
+  if (__Pyx_ExportFunction("_read_Fst_from_string", (void (*)(void))__pyx_f_9pywrapfst__read_Fst_from_string, "struct __pyx_obj_9pywrapfst__Fst *(PyObject *, int __pyx_skip_dispatch)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("_init_Arc", (void (*)(void))__pyx_f_9pywrapfst__init_Arc, "struct __pyx_obj_9pywrapfst_Arc *(fst::script::ArcClass const &)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("_map", (void (*)(void))__pyx_f_9pywrapfst__map, "struct __pyx_obj_9pywrapfst__Fst *(struct __pyx_obj_9pywrapfst__Fst *, struct __pyx_opt_args_9pywrapfst__map *__pyx_optional_args)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   if (__Pyx_ExportFunction("arcmap", (void (*)(void))__pyx_f_9pywrapfst_arcmap, "struct __pyx_obj_9pywrapfst__Fst *(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch, struct __pyx_opt_args_9pywrapfst_arcmap *__pyx_optional_args)") < 0) __PYX_ERR(0, 1, __pyx_L1_error)
@@ -50594,58 +49034,56 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst_Weight.copy = (struct __pyx_obj_9pywrapfst_Weight *(*)(struct __pyx_obj_9pywrapfst_Weight *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_6Weight_copy;
   __pyx_vtable_9pywrapfst_Weight.to_string = (std::string (*)(struct __pyx_obj_9pywrapfst_Weight *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_6Weight_to_string;
   __pyx_vtable_9pywrapfst_Weight.type = (std::string (*)(struct __pyx_obj_9pywrapfst_Weight *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_6Weight_type;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_Weight) < 0) __PYX_ERR(0, 348, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_Weight) < 0) __PYX_ERR(0, 333, __pyx_L1_error)
   __pyx_type_9pywrapfst_Weight.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_Weight.tp_dictoffset && __pyx_type_9pywrapfst_Weight.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_Weight.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_Weight.tp_dict, __pyx_vtabptr_9pywrapfst_Weight) < 0) __PYX_ERR(0, 348, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "Weight", (PyObject *)&__pyx_type_9pywrapfst_Weight) < 0) __PYX_ERR(0, 348, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_Weight) < 0) __PYX_ERR(0, 348, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_Weight.tp_dict, __pyx_vtabptr_9pywrapfst_Weight) < 0) __PYX_ERR(0, 333, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_Weight, (PyObject *)&__pyx_type_9pywrapfst_Weight) < 0) __PYX_ERR(0, 333, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_Weight) < 0) __PYX_ERR(0, 333, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_Weight = &__pyx_type_9pywrapfst_Weight;
   __pyx_vtabptr_9pywrapfst__SymbolTable = &__pyx_vtable_9pywrapfst__SymbolTable;
   __pyx_vtable_9pywrapfst__SymbolTable.available_key = (__pyx_t_10basictypes_int64 (*)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_available_key;
-  __pyx_vtable_9pywrapfst__SymbolTable.checksum = (std::string (*)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_checksum;
+  __pyx_vtable_9pywrapfst__SymbolTable.checksum = (PyObject *(*)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_checksum;
   __pyx_vtable_9pywrapfst__SymbolTable.copy = (struct __pyx_obj_9pywrapfst_SymbolTable *(*)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_copy;
   __pyx_vtable_9pywrapfst__SymbolTable.get_nth_key = (__pyx_t_10basictypes_int64 (*)(struct __pyx_obj_9pywrapfst__SymbolTable *, Py_ssize_t, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_get_nth_key;
-  __pyx_vtable_9pywrapfst__SymbolTable.labeled_checksum = (std::string (*)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_labeled_checksum;
+  __pyx_vtable_9pywrapfst__SymbolTable.labeled_checksum = (PyObject *(*)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_labeled_checksum;
   __pyx_vtable_9pywrapfst__SymbolTable.member = (bool (*)(struct __pyx_obj_9pywrapfst__SymbolTable *, PyObject *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_member;
   __pyx_vtable_9pywrapfst__SymbolTable.name = (std::string (*)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_name;
   __pyx_vtable_9pywrapfst__SymbolTable.num_symbols = (size_t (*)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_num_symbols;
   __pyx_vtable_9pywrapfst__SymbolTable.write = (void (*)(struct __pyx_obj_9pywrapfst__SymbolTable *, PyObject *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_write;
   __pyx_vtable_9pywrapfst__SymbolTable.write_text = (void (*)(struct __pyx_obj_9pywrapfst__SymbolTable *, PyObject *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_write_text;
-  if (PyType_Ready(&__pyx_type_9pywrapfst__SymbolTable) < 0) __PYX_ERR(0, 675, __pyx_L1_error)
+  __pyx_vtable_9pywrapfst__SymbolTable.write_to_string = (PyObject *(*)(struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12_SymbolTable_write_to_string;
+  if (PyType_Ready(&__pyx_type_9pywrapfst__SymbolTable) < 0) __PYX_ERR(0, 660, __pyx_L1_error)
   __pyx_type_9pywrapfst__SymbolTable.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst__SymbolTable.tp_dictoffset && __pyx_type_9pywrapfst__SymbolTable.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst__SymbolTable.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__SymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__SymbolTable) < 0) __PYX_ERR(0, 675, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "_SymbolTable", (PyObject *)&__pyx_type_9pywrapfst__SymbolTable) < 0) __PYX_ERR(0, 675, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst__SymbolTable) < 0) __PYX_ERR(0, 675, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__SymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__SymbolTable) < 0) __PYX_ERR(0, 660, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_SymbolTable, (PyObject *)&__pyx_type_9pywrapfst__SymbolTable) < 0) __PYX_ERR(0, 660, __pyx_L1_error)
   __pyx_ptype_9pywrapfst__SymbolTable = &__pyx_type_9pywrapfst__SymbolTable;
   __pyx_vtabptr_9pywrapfst__EncodeMapperSymbolTable = &__pyx_vtable_9pywrapfst__EncodeMapperSymbolTable;
   __pyx_vtable_9pywrapfst__EncodeMapperSymbolTable.__pyx_base = *__pyx_vtabptr_9pywrapfst__SymbolTable;
   __pyx_type_9pywrapfst__EncodeMapperSymbolTable.tp_base = __pyx_ptype_9pywrapfst__SymbolTable;
-  if (PyType_Ready(&__pyx_type_9pywrapfst__EncodeMapperSymbolTable) < 0) __PYX_ERR(0, 839, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst__EncodeMapperSymbolTable) < 0) __PYX_ERR(0, 848, __pyx_L1_error)
   __pyx_type_9pywrapfst__EncodeMapperSymbolTable.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst__EncodeMapperSymbolTable.tp_dictoffset && __pyx_type_9pywrapfst__EncodeMapperSymbolTable.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst__EncodeMapperSymbolTable.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__EncodeMapperSymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__EncodeMapperSymbolTable) < 0) __PYX_ERR(0, 839, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "_EncodeMapperSymbolTable", (PyObject *)&__pyx_type_9pywrapfst__EncodeMapperSymbolTable) < 0) __PYX_ERR(0, 839, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst__EncodeMapperSymbolTable) < 0) __PYX_ERR(0, 839, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__EncodeMapperSymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__EncodeMapperSymbolTable) < 0) __PYX_ERR(0, 848, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_EncodeMapperSymbolTable, (PyObject *)&__pyx_type_9pywrapfst__EncodeMapperSymbolTable) < 0) __PYX_ERR(0, 848, __pyx_L1_error)
   __pyx_ptype_9pywrapfst__EncodeMapperSymbolTable = &__pyx_type_9pywrapfst__EncodeMapperSymbolTable;
   __pyx_vtabptr_9pywrapfst__FstSymbolTable = &__pyx_vtable_9pywrapfst__FstSymbolTable;
   __pyx_vtable_9pywrapfst__FstSymbolTable.__pyx_base = *__pyx_vtabptr_9pywrapfst__SymbolTable;
   __pyx_type_9pywrapfst__FstSymbolTable.tp_base = __pyx_ptype_9pywrapfst__SymbolTable;
-  if (PyType_Ready(&__pyx_type_9pywrapfst__FstSymbolTable) < 0) __PYX_ERR(0, 859, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst__FstSymbolTable) < 0) __PYX_ERR(0, 868, __pyx_L1_error)
   __pyx_type_9pywrapfst__FstSymbolTable.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst__FstSymbolTable.tp_dictoffset && __pyx_type_9pywrapfst__FstSymbolTable.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst__FstSymbolTable.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__FstSymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__FstSymbolTable) < 0) __PYX_ERR(0, 859, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "_FstSymbolTable", (PyObject *)&__pyx_type_9pywrapfst__FstSymbolTable) < 0) __PYX_ERR(0, 859, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst__FstSymbolTable) < 0) __PYX_ERR(0, 859, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__FstSymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__FstSymbolTable) < 0) __PYX_ERR(0, 868, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_FstSymbolTable, (PyObject *)&__pyx_type_9pywrapfst__FstSymbolTable) < 0) __PYX_ERR(0, 868, __pyx_L1_error)
   __pyx_ptype_9pywrapfst__FstSymbolTable = &__pyx_type_9pywrapfst__FstSymbolTable;
   __pyx_vtabptr_9pywrapfst__MutableSymbolTable = &__pyx_vtable_9pywrapfst__MutableSymbolTable;
   __pyx_vtable_9pywrapfst__MutableSymbolTable.__pyx_base = *__pyx_vtabptr_9pywrapfst__SymbolTable;
@@ -50653,38 +49091,35 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst__MutableSymbolTable.add_table = (void (*)(struct __pyx_obj_9pywrapfst__MutableSymbolTable *, struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_19_MutableSymbolTable_add_table;
   __pyx_vtable_9pywrapfst__MutableSymbolTable.set_name = (void (*)(struct __pyx_obj_9pywrapfst__MutableSymbolTable *, PyObject *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_19_MutableSymbolTable_set_name;
   __pyx_type_9pywrapfst__MutableSymbolTable.tp_base = __pyx_ptype_9pywrapfst__SymbolTable;
-  if (PyType_Ready(&__pyx_type_9pywrapfst__MutableSymbolTable) < 0) __PYX_ERR(0, 878, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst__MutableSymbolTable) < 0) __PYX_ERR(0, 887, __pyx_L1_error)
   __pyx_type_9pywrapfst__MutableSymbolTable.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst__MutableSymbolTable.tp_dictoffset && __pyx_type_9pywrapfst__MutableSymbolTable.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst__MutableSymbolTable.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__MutableSymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__MutableSymbolTable) < 0) __PYX_ERR(0, 878, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "_MutableSymbolTable", (PyObject *)&__pyx_type_9pywrapfst__MutableSymbolTable) < 0) __PYX_ERR(0, 878, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst__MutableSymbolTable) < 0) __PYX_ERR(0, 878, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__MutableSymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__MutableSymbolTable) < 0) __PYX_ERR(0, 887, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_MutableSymbolTable, (PyObject *)&__pyx_type_9pywrapfst__MutableSymbolTable) < 0) __PYX_ERR(0, 887, __pyx_L1_error)
   __pyx_ptype_9pywrapfst__MutableSymbolTable = &__pyx_type_9pywrapfst__MutableSymbolTable;
   __pyx_vtabptr_9pywrapfst__MutableFstSymbolTable = &__pyx_vtable_9pywrapfst__MutableFstSymbolTable;
   __pyx_vtable_9pywrapfst__MutableFstSymbolTable.__pyx_base = *__pyx_vtabptr_9pywrapfst__MutableSymbolTable;
   __pyx_type_9pywrapfst__MutableFstSymbolTable.tp_base = __pyx_ptype_9pywrapfst__MutableSymbolTable;
-  if (PyType_Ready(&__pyx_type_9pywrapfst__MutableFstSymbolTable) < 0) __PYX_ERR(0, 930, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst__MutableFstSymbolTable) < 0) __PYX_ERR(0, 939, __pyx_L1_error)
   __pyx_type_9pywrapfst__MutableFstSymbolTable.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst__MutableFstSymbolTable.tp_dictoffset && __pyx_type_9pywrapfst__MutableFstSymbolTable.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst__MutableFstSymbolTable.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__MutableFstSymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__MutableFstSymbolTable) < 0) __PYX_ERR(0, 930, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "_MutableFstSymbolTable", (PyObject *)&__pyx_type_9pywrapfst__MutableFstSymbolTable) < 0) __PYX_ERR(0, 930, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst__MutableFstSymbolTable) < 0) __PYX_ERR(0, 930, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__MutableFstSymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst__MutableFstSymbolTable) < 0) __PYX_ERR(0, 939, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_MutableFstSymbolTable, (PyObject *)&__pyx_type_9pywrapfst__MutableFstSymbolTable) < 0) __PYX_ERR(0, 939, __pyx_L1_error)
   __pyx_ptype_9pywrapfst__MutableFstSymbolTable = &__pyx_type_9pywrapfst__MutableFstSymbolTable;
   __pyx_vtabptr_9pywrapfst_SymbolTable = &__pyx_vtable_9pywrapfst_SymbolTable;
   __pyx_vtable_9pywrapfst_SymbolTable.__pyx_base = *__pyx_vtabptr_9pywrapfst__MutableSymbolTable;
   __pyx_type_9pywrapfst_SymbolTable.tp_base = __pyx_ptype_9pywrapfst__MutableSymbolTable;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_SymbolTable) < 0) __PYX_ERR(0, 941, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_SymbolTable) < 0) __PYX_ERR(0, 950, __pyx_L1_error)
   __pyx_type_9pywrapfst_SymbolTable.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_SymbolTable.tp_dictoffset && __pyx_type_9pywrapfst_SymbolTable.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_SymbolTable.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_SymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst_SymbolTable) < 0) __PYX_ERR(0, 941, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "SymbolTable", (PyObject *)&__pyx_type_9pywrapfst_SymbolTable) < 0) __PYX_ERR(0, 941, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_SymbolTable) < 0) __PYX_ERR(0, 941, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_SymbolTable.tp_dict, __pyx_vtabptr_9pywrapfst_SymbolTable) < 0) __PYX_ERR(0, 950, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_SymbolTable_2, (PyObject *)&__pyx_type_9pywrapfst_SymbolTable) < 0) __PYX_ERR(0, 950, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_SymbolTable = &__pyx_type_9pywrapfst_SymbolTable;
   __pyx_vtabptr_9pywrapfst_SymbolTableIterator = &__pyx_vtable_9pywrapfst_SymbolTableIterator;
   __pyx_vtable_9pywrapfst_SymbolTableIterator.done = (bool (*)(struct __pyx_obj_9pywrapfst_SymbolTableIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_19SymbolTableIterator_done;
@@ -50692,14 +49127,14 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst_SymbolTableIterator.reset = (void (*)(struct __pyx_obj_9pywrapfst_SymbolTableIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_19SymbolTableIterator_reset;
   __pyx_vtable_9pywrapfst_SymbolTableIterator.symbol = (std::string (*)(struct __pyx_obj_9pywrapfst_SymbolTableIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_19SymbolTableIterator_symbol;
   __pyx_vtable_9pywrapfst_SymbolTableIterator.value = (__pyx_t_10basictypes_int64 (*)(struct __pyx_obj_9pywrapfst_SymbolTableIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_19SymbolTableIterator_value;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_SymbolTableIterator) < 0) __PYX_ERR(0, 1124, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_SymbolTableIterator) < 0) __PYX_ERR(0, 1145, __pyx_L1_error)
   __pyx_type_9pywrapfst_SymbolTableIterator.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_SymbolTableIterator.tp_dictoffset && __pyx_type_9pywrapfst_SymbolTableIterator.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_SymbolTableIterator.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_SymbolTableIterator.tp_dict, __pyx_vtabptr_9pywrapfst_SymbolTableIterator) < 0) __PYX_ERR(0, 1124, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "SymbolTableIterator", (PyObject *)&__pyx_type_9pywrapfst_SymbolTableIterator) < 0) __PYX_ERR(0, 1124, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_SymbolTableIterator) < 0) __PYX_ERR(0, 1124, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_SymbolTableIterator.tp_dict, __pyx_vtabptr_9pywrapfst_SymbolTableIterator) < 0) __PYX_ERR(0, 1145, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_SymbolTableIterator, (PyObject *)&__pyx_type_9pywrapfst_SymbolTableIterator) < 0) __PYX_ERR(0, 1145, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_SymbolTableIterator) < 0) __PYX_ERR(0, 1145, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_SymbolTableIterator = &__pyx_type_9pywrapfst_SymbolTableIterator;
   __pyx_vtabptr_9pywrapfst_EncodeMapper = &__pyx_vtable_9pywrapfst_EncodeMapper;
   __pyx_vtable_9pywrapfst_EncodeMapper.arc_type = (std::string (*)(struct __pyx_obj_9pywrapfst_EncodeMapper *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12EncodeMapper_arc_type;
@@ -50710,14 +49145,14 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst_EncodeMapper.set_input_symbols = (void (*)(struct __pyx_obj_9pywrapfst_EncodeMapper *, struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12EncodeMapper_set_input_symbols;
   __pyx_vtable_9pywrapfst_EncodeMapper.set_output_symbols = (void (*)(struct __pyx_obj_9pywrapfst_EncodeMapper *, struct __pyx_obj_9pywrapfst__SymbolTable *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12EncodeMapper_set_output_symbols;
   __pyx_vtable_9pywrapfst_EncodeMapper.weight_type = (std::string (*)(struct __pyx_obj_9pywrapfst_EncodeMapper *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_12EncodeMapper_weight_type;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_EncodeMapper) < 0) __PYX_ERR(0, 1206, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_EncodeMapper) < 0) __PYX_ERR(0, 1227, __pyx_L1_error)
   __pyx_type_9pywrapfst_EncodeMapper.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_EncodeMapper.tp_dictoffset && __pyx_type_9pywrapfst_EncodeMapper.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_EncodeMapper.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
   #if CYTHON_COMPILING_IN_CPYTHON
   {
-    PyObject *wrapper = PyObject_GetAttrString((PyObject *)&__pyx_type_9pywrapfst_EncodeMapper, "__call__"); if (unlikely(!wrapper)) __PYX_ERR(0, 1206, __pyx_L1_error)
+    PyObject *wrapper = PyObject_GetAttrString((PyObject *)&__pyx_type_9pywrapfst_EncodeMapper, "__call__"); if (unlikely(!wrapper)) __PYX_ERR(0, 1227, __pyx_L1_error)
     if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) {
       __pyx_wrapperbase_9pywrapfst_12EncodeMapper_6__call__ = *((PyWrapperDescrObject *)wrapper)->d_base;
       __pyx_wrapperbase_9pywrapfst_12EncodeMapper_6__call__.doc = __pyx_doc_9pywrapfst_12EncodeMapper_6__call__;
@@ -50725,11 +49160,12 @@ static int __Pyx_modinit_type_init_code(void) {
     }
   }
   #endif
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_EncodeMapper.tp_dict, __pyx_vtabptr_9pywrapfst_EncodeMapper) < 0) __PYX_ERR(0, 1206, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "EncodeMapper", (PyObject *)&__pyx_type_9pywrapfst_EncodeMapper) < 0) __PYX_ERR(0, 1206, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_EncodeMapper) < 0) __PYX_ERR(0, 1206, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_EncodeMapper.tp_dict, __pyx_vtabptr_9pywrapfst_EncodeMapper) < 0) __PYX_ERR(0, 1227, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_EncodeMapper, (PyObject *)&__pyx_type_9pywrapfst_EncodeMapper) < 0) __PYX_ERR(0, 1227, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_EncodeMapper) < 0) __PYX_ERR(0, 1227, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_EncodeMapper = &__pyx_type_9pywrapfst_EncodeMapper;
   __pyx_vtabptr_9pywrapfst__Fst = &__pyx_vtable_9pywrapfst__Fst;
+  __pyx_vtable_9pywrapfst__Fst._local_render_svg = (std::string (*)(std::string const &))__pyx_f_9pywrapfst_4_Fst__local_render_svg;
   __pyx_vtable_9pywrapfst__Fst.arc_type = (std::string (*)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_4_Fst_arc_type;
   __pyx_vtable_9pywrapfst__Fst.arcs = (struct __pyx_obj_9pywrapfst_ArcIterator *(*)(struct __pyx_obj_9pywrapfst__Fst *, __pyx_t_10basictypes_int64, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_4_Fst_arcs;
   __pyx_vtable_9pywrapfst__Fst.copy = (struct __pyx_obj_9pywrapfst__Fst *(*)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_4_Fst_copy;
@@ -50748,14 +49184,14 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst__Fst.verify = (bool (*)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_4_Fst_verify;
   __pyx_vtable_9pywrapfst__Fst.weight_type = (std::string (*)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_4_Fst_weight_type;
   __pyx_vtable_9pywrapfst__Fst.write = (void (*)(struct __pyx_obj_9pywrapfst__Fst *, PyObject *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_4_Fst_write;
-  __pyx_vtable_9pywrapfst__Fst.write_to_string = (std::string (*)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_4_Fst_write_to_string;
-  if (PyType_Ready(&__pyx_type_9pywrapfst__Fst) < 0) __PYX_ERR(0, 1362, __pyx_L1_error)
+  __pyx_vtable_9pywrapfst__Fst.write_to_string = (PyObject *(*)(struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_4_Fst_write_to_string;
+  if (PyType_Ready(&__pyx_type_9pywrapfst__Fst) < 0) __PYX_ERR(0, 1383, __pyx_L1_error)
   __pyx_type_9pywrapfst__Fst.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst__Fst.tp_dictoffset && __pyx_type_9pywrapfst__Fst.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst__Fst.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__Fst.tp_dict, __pyx_vtabptr_9pywrapfst__Fst) < 0) __PYX_ERR(0, 1362, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "_Fst", (PyObject *)&__pyx_type_9pywrapfst__Fst) < 0) __PYX_ERR(0, 1362, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__Fst.tp_dict, __pyx_vtabptr_9pywrapfst__Fst) < 0) __PYX_ERR(0, 1383, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_Fst, (PyObject *)&__pyx_type_9pywrapfst__Fst) < 0) __PYX_ERR(0, 1383, __pyx_L1_error)
   __pyx_ptype_9pywrapfst__Fst = &__pyx_type_9pywrapfst__Fst;
   __pyx_vtabptr_9pywrapfst__MutableFst = &__pyx_vtable_9pywrapfst__MutableFst;
   __pyx_vtable_9pywrapfst__MutableFst.__pyx_base = *__pyx_vtabptr_9pywrapfst__Fst;
@@ -50791,24 +49227,24 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst__MutableFst._topsort = (void (*)(struct __pyx_obj_9pywrapfst__MutableFst *))__pyx_f_9pywrapfst_11_MutableFst__topsort;
   __pyx_vtable_9pywrapfst__MutableFst._union = (void (*)(struct __pyx_obj_9pywrapfst__MutableFst *, struct __pyx_obj_9pywrapfst__Fst *))__pyx_f_9pywrapfst_11_MutableFst__union;
   __pyx_type_9pywrapfst__MutableFst.tp_base = __pyx_ptype_9pywrapfst__Fst;
-  if (PyType_Ready(&__pyx_type_9pywrapfst__MutableFst) < 0) __PYX_ERR(0, 1774, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst__MutableFst) < 0) __PYX_ERR(0, 1798, __pyx_L1_error)
   __pyx_type_9pywrapfst__MutableFst.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst__MutableFst.tp_dictoffset && __pyx_type_9pywrapfst__MutableFst.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst__MutableFst.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__MutableFst.tp_dict, __pyx_vtabptr_9pywrapfst__MutableFst) < 0) __PYX_ERR(0, 1774, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "_MutableFst", (PyObject *)&__pyx_type_9pywrapfst__MutableFst) < 0) __PYX_ERR(0, 1774, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst__MutableFst.tp_dict, __pyx_vtabptr_9pywrapfst__MutableFst) < 0) __PYX_ERR(0, 1798, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_MutableFst, (PyObject *)&__pyx_type_9pywrapfst__MutableFst) < 0) __PYX_ERR(0, 1798, __pyx_L1_error)
   __pyx_ptype_9pywrapfst__MutableFst = &__pyx_type_9pywrapfst__MutableFst;
   __pyx_vtabptr_9pywrapfst_Arc = &__pyx_vtable_9pywrapfst_Arc;
   __pyx_vtable_9pywrapfst_Arc.copy = (struct __pyx_obj_9pywrapfst_Arc *(*)(struct __pyx_obj_9pywrapfst_Arc *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_3Arc_copy;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_Arc) < 0) __PYX_ERR(0, 2898, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_Arc) < 0) __PYX_ERR(0, 2916, __pyx_L1_error)
   __pyx_type_9pywrapfst_Arc.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_Arc.tp_dictoffset && __pyx_type_9pywrapfst_Arc.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_Arc.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_Arc.tp_dict, __pyx_vtabptr_9pywrapfst_Arc) < 0) __PYX_ERR(0, 2898, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "Arc", (PyObject *)&__pyx_type_9pywrapfst_Arc) < 0) __PYX_ERR(0, 2898, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_Arc) < 0) __PYX_ERR(0, 2898, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_Arc.tp_dict, __pyx_vtabptr_9pywrapfst_Arc) < 0) __PYX_ERR(0, 2916, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_Arc, (PyObject *)&__pyx_type_9pywrapfst_Arc) < 0) __PYX_ERR(0, 2916, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_Arc) < 0) __PYX_ERR(0, 2916, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_Arc = &__pyx_type_9pywrapfst_Arc;
   __pyx_vtabptr_9pywrapfst_ArcIterator = &__pyx_vtable_9pywrapfst_ArcIterator;
   __pyx_vtable_9pywrapfst_ArcIterator.done = (bool (*)(struct __pyx_obj_9pywrapfst_ArcIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_11ArcIterator_done;
@@ -50819,14 +49255,14 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst_ArcIterator.seek = (void (*)(struct __pyx_obj_9pywrapfst_ArcIterator *, size_t, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_11ArcIterator_seek;
   __pyx_vtable_9pywrapfst_ArcIterator.set_flags = (void (*)(struct __pyx_obj_9pywrapfst_ArcIterator *, __pyx_t_10basictypes_uint32, __pyx_t_10basictypes_uint32, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_11ArcIterator_set_flags;
   __pyx_vtable_9pywrapfst_ArcIterator.value = (PyObject *(*)(struct __pyx_obj_9pywrapfst_ArcIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_11ArcIterator_value;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_ArcIterator) < 0) __PYX_ERR(0, 2965, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_ArcIterator) < 0) __PYX_ERR(0, 2983, __pyx_L1_error)
   __pyx_type_9pywrapfst_ArcIterator.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_ArcIterator.tp_dictoffset && __pyx_type_9pywrapfst_ArcIterator.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_ArcIterator.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_ArcIterator.tp_dict, __pyx_vtabptr_9pywrapfst_ArcIterator) < 0) __PYX_ERR(0, 2965, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "ArcIterator", (PyObject *)&__pyx_type_9pywrapfst_ArcIterator) < 0) __PYX_ERR(0, 2965, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_ArcIterator) < 0) __PYX_ERR(0, 2965, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_ArcIterator.tp_dict, __pyx_vtabptr_9pywrapfst_ArcIterator) < 0) __PYX_ERR(0, 2983, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_ArcIterator, (PyObject *)&__pyx_type_9pywrapfst_ArcIterator) < 0) __PYX_ERR(0, 2983, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_ArcIterator) < 0) __PYX_ERR(0, 2983, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_ArcIterator = &__pyx_type_9pywrapfst_ArcIterator;
   __pyx_vtabptr_9pywrapfst_MutableArcIterator = &__pyx_vtable_9pywrapfst_MutableArcIterator;
   __pyx_vtable_9pywrapfst_MutableArcIterator.done = (bool (*)(struct __pyx_obj_9pywrapfst_MutableArcIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_18MutableArcIterator_done;
@@ -50838,40 +49274,40 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst_MutableArcIterator.set_flags = (void (*)(struct __pyx_obj_9pywrapfst_MutableArcIterator *, __pyx_t_10basictypes_uint32, __pyx_t_10basictypes_uint32, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_18MutableArcIterator_set_flags;
   __pyx_vtable_9pywrapfst_MutableArcIterator.set_value = (void (*)(struct __pyx_obj_9pywrapfst_MutableArcIterator *, struct __pyx_obj_9pywrapfst_Arc *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_18MutableArcIterator_set_value;
   __pyx_vtable_9pywrapfst_MutableArcIterator.value = (PyObject *(*)(struct __pyx_obj_9pywrapfst_MutableArcIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_18MutableArcIterator_value;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_MutableArcIterator) < 0) __PYX_ERR(0, 3076, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_MutableArcIterator) < 0) __PYX_ERR(0, 3094, __pyx_L1_error)
   __pyx_type_9pywrapfst_MutableArcIterator.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_MutableArcIterator.tp_dictoffset && __pyx_type_9pywrapfst_MutableArcIterator.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_MutableArcIterator.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_MutableArcIterator.tp_dict, __pyx_vtabptr_9pywrapfst_MutableArcIterator) < 0) __PYX_ERR(0, 3076, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "MutableArcIterator", (PyObject *)&__pyx_type_9pywrapfst_MutableArcIterator) < 0) __PYX_ERR(0, 3076, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_MutableArcIterator) < 0) __PYX_ERR(0, 3076, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_MutableArcIterator.tp_dict, __pyx_vtabptr_9pywrapfst_MutableArcIterator) < 0) __PYX_ERR(0, 3094, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_MutableArcIterator, (PyObject *)&__pyx_type_9pywrapfst_MutableArcIterator) < 0) __PYX_ERR(0, 3094, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_MutableArcIterator) < 0) __PYX_ERR(0, 3094, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_MutableArcIterator = &__pyx_type_9pywrapfst_MutableArcIterator;
   __pyx_vtabptr_9pywrapfst_StateIterator = &__pyx_vtable_9pywrapfst_StateIterator;
   __pyx_vtable_9pywrapfst_StateIterator.done = (bool (*)(struct __pyx_obj_9pywrapfst_StateIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_13StateIterator_done;
   __pyx_vtable_9pywrapfst_StateIterator.next = (void (*)(struct __pyx_obj_9pywrapfst_StateIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_13StateIterator_next;
   __pyx_vtable_9pywrapfst_StateIterator.reset = (void (*)(struct __pyx_obj_9pywrapfst_StateIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_13StateIterator_reset;
   __pyx_vtable_9pywrapfst_StateIterator.value = (__pyx_t_10basictypes_int64 (*)(struct __pyx_obj_9pywrapfst_StateIterator *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_13StateIterator_value;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_StateIterator) < 0) __PYX_ERR(0, 3190, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_StateIterator) < 0) __PYX_ERR(0, 3208, __pyx_L1_error)
   __pyx_type_9pywrapfst_StateIterator.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_StateIterator.tp_dictoffset && __pyx_type_9pywrapfst_StateIterator.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_StateIterator.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_StateIterator.tp_dict, __pyx_vtabptr_9pywrapfst_StateIterator) < 0) __PYX_ERR(0, 3190, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "StateIterator", (PyObject *)&__pyx_type_9pywrapfst_StateIterator) < 0) __PYX_ERR(0, 3190, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_StateIterator) < 0) __PYX_ERR(0, 3190, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_StateIterator.tp_dict, __pyx_vtabptr_9pywrapfst_StateIterator) < 0) __PYX_ERR(0, 3208, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_StateIterator, (PyObject *)&__pyx_type_9pywrapfst_StateIterator) < 0) __PYX_ERR(0, 3208, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_StateIterator) < 0) __PYX_ERR(0, 3208, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_StateIterator = &__pyx_type_9pywrapfst_StateIterator;
   __pyx_vtabptr_9pywrapfst_Compiler = &__pyx_vtable_9pywrapfst_Compiler;
   __pyx_vtable_9pywrapfst_Compiler.compile = (struct __pyx_obj_9pywrapfst__Fst *(*)(struct __pyx_obj_9pywrapfst_Compiler *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_8Compiler_compile;
   __pyx_vtable_9pywrapfst_Compiler.write = (void (*)(struct __pyx_obj_9pywrapfst_Compiler *, PyObject *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_8Compiler_write;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_Compiler) < 0) __PYX_ERR(0, 4088, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_Compiler) < 0) __PYX_ERR(0, 4106, __pyx_L1_error)
   __pyx_type_9pywrapfst_Compiler.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_Compiler.tp_dictoffset && __pyx_type_9pywrapfst_Compiler.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_Compiler.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_Compiler.tp_dict, __pyx_vtabptr_9pywrapfst_Compiler) < 0) __PYX_ERR(0, 4088, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "Compiler", (PyObject *)&__pyx_type_9pywrapfst_Compiler) < 0) __PYX_ERR(0, 4088, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_Compiler) < 0) __PYX_ERR(0, 4088, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_Compiler.tp_dict, __pyx_vtabptr_9pywrapfst_Compiler) < 0) __PYX_ERR(0, 4106, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_Compiler, (PyObject *)&__pyx_type_9pywrapfst_Compiler) < 0) __PYX_ERR(0, 4106, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_Compiler) < 0) __PYX_ERR(0, 4106, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_Compiler = &__pyx_type_9pywrapfst_Compiler;
   __pyx_vtabptr_9pywrapfst_FarReader = &__pyx_vtable_9pywrapfst_FarReader;
   __pyx_vtable_9pywrapfst_FarReader.arc_type = (std::string (*)(struct __pyx_obj_9pywrapfst_FarReader *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_9FarReader_arc_type;
@@ -50883,14 +49319,14 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst_FarReader.get_key = (std::string (*)(struct __pyx_obj_9pywrapfst_FarReader *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_9FarReader_get_key;
   __pyx_vtable_9pywrapfst_FarReader.next = (void (*)(struct __pyx_obj_9pywrapfst_FarReader *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_9FarReader_next;
   __pyx_vtable_9pywrapfst_FarReader.reset = (void (*)(struct __pyx_obj_9pywrapfst_FarReader *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_9FarReader_reset;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_FarReader) < 0) __PYX_ERR(0, 4215, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_FarReader) < 0) __PYX_ERR(0, 4236, __pyx_L1_error)
   __pyx_type_9pywrapfst_FarReader.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_FarReader.tp_dictoffset && __pyx_type_9pywrapfst_FarReader.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_FarReader.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_FarReader.tp_dict, __pyx_vtabptr_9pywrapfst_FarReader) < 0) __PYX_ERR(0, 4215, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "FarReader", (PyObject *)&__pyx_type_9pywrapfst_FarReader) < 0) __PYX_ERR(0, 4215, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_FarReader) < 0) __PYX_ERR(0, 4215, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_FarReader.tp_dict, __pyx_vtabptr_9pywrapfst_FarReader) < 0) __PYX_ERR(0, 4236, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_FarReader, (PyObject *)&__pyx_type_9pywrapfst_FarReader) < 0) __PYX_ERR(0, 4236, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_FarReader) < 0) __PYX_ERR(0, 4236, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_FarReader = &__pyx_type_9pywrapfst_FarReader;
   __pyx_vtabptr_9pywrapfst_FarWriter = &__pyx_vtable_9pywrapfst_FarWriter;
   __pyx_vtable_9pywrapfst_FarWriter.arc_type = (std::string (*)(struct __pyx_obj_9pywrapfst_FarWriter *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_9FarWriter_arc_type;
@@ -50898,14 +49334,14 @@ static int __Pyx_modinit_type_init_code(void) {
   __pyx_vtable_9pywrapfst_FarWriter.add = (void (*)(struct __pyx_obj_9pywrapfst_FarWriter *, PyObject *, struct __pyx_obj_9pywrapfst__Fst *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_9FarWriter_add;
   __pyx_vtable_9pywrapfst_FarWriter.error = (bool (*)(struct __pyx_obj_9pywrapfst_FarWriter *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_9FarWriter_error;
   __pyx_vtable_9pywrapfst_FarWriter.far_type = (std::string (*)(struct __pyx_obj_9pywrapfst_FarWriter *, int __pyx_skip_dispatch))__pyx_f_9pywrapfst_9FarWriter_far_type;
-  if (PyType_Ready(&__pyx_type_9pywrapfst_FarWriter) < 0) __PYX_ERR(0, 4361, __pyx_L1_error)
+  if (PyType_Ready(&__pyx_type_9pywrapfst_FarWriter) < 0) __PYX_ERR(0, 4383, __pyx_L1_error)
   __pyx_type_9pywrapfst_FarWriter.tp_print = 0;
   if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_9pywrapfst_FarWriter.tp_dictoffset && __pyx_type_9pywrapfst_FarWriter.tp_getattro == PyObject_GenericGetAttr)) {
     __pyx_type_9pywrapfst_FarWriter.tp_getattro = __Pyx_PyObject_GenericGetAttr;
   }
-  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_FarWriter.tp_dict, __pyx_vtabptr_9pywrapfst_FarWriter) < 0) __PYX_ERR(0, 4361, __pyx_L1_error)
-  if (PyObject_SetAttrString(__pyx_m, "FarWriter", (PyObject *)&__pyx_type_9pywrapfst_FarWriter) < 0) __PYX_ERR(0, 4361, __pyx_L1_error)
-  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_FarWriter) < 0) __PYX_ERR(0, 4361, __pyx_L1_error)
+  if (__Pyx_SetVtable(__pyx_type_9pywrapfst_FarWriter.tp_dict, __pyx_vtabptr_9pywrapfst_FarWriter) < 0) __PYX_ERR(0, 4383, __pyx_L1_error)
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s_FarWriter, (PyObject *)&__pyx_type_9pywrapfst_FarWriter) < 0) __PYX_ERR(0, 4383, __pyx_L1_error)
+  if (__Pyx_setup_reduce((PyObject*)&__pyx_type_9pywrapfst_FarWriter) < 0) __PYX_ERR(0, 4383, __pyx_L1_error)
   __pyx_ptype_9pywrapfst_FarWriter = &__pyx_type_9pywrapfst_FarWriter;
   __Pyx_RefNannyFinishContext();
   return 0;
@@ -50952,15 +49388,6 @@ static int __Pyx_modinit_function_import_code(void) {
 #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC
 #endif
 #endif
-#ifndef CYTHON_SMALL_CODE
-#if defined(__clang__)
-    #define CYTHON_SMALL_CODE
-#elif defined(__GNUC__) && (!(defined(__cplusplus)) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4)))
-    #define CYTHON_SMALL_CODE __attribute__((optimize("Os")))
-#else
-    #define CYTHON_SMALL_CODE
-#endif
-#endif
 
 
 #if PY_MAJOR_VERSION < 3
@@ -50973,7 +49400,30 @@ __Pyx_PyMODINIT_FUNC PyInit_pywrapfst(void)
 {
   return PyModuleDef_Init(&__pyx_moduledef);
 }
-static int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name) {
+static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) {
+    #if PY_VERSION_HEX >= 0x030700A1
+    static PY_INT64_T main_interpreter_id = -1;
+    PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp);
+    if (main_interpreter_id == -1) {
+        main_interpreter_id = current_id;
+        return (unlikely(current_id == -1)) ? -1 : 0;
+    } else if (unlikely(main_interpreter_id != current_id))
+    #else
+    static PyInterpreterState *main_interpreter = NULL;
+    PyInterpreterState *current_interpreter = PyThreadState_Get()->interp;
+    if (!main_interpreter) {
+        main_interpreter = current_interpreter;
+    } else if (unlikely(main_interpreter != current_interpreter))
+    #endif
+    {
+        PyErr_SetString(
+            PyExc_ImportError,
+            "Interpreter change detected - this module can only be loaded into one interpreter per process.");
+        return -1;
+    }
+    return 0;
+}
+static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name) {
     PyObject *value = PyObject_GetAttrString(spec, from_name);
     int result = 0;
     if (likely(value)) {
@@ -50986,8 +49436,10 @@ static int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const ch
     }
     return result;
 }
-static PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) {
+static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) {
     PyObject *module = NULL, *moddict, *modname;
+    if (__Pyx_check_single_interpreter())
+        return NULL;
     if (__pyx_m)
         return __Pyx_NewRef(__pyx_m);
     modname = PyObject_GetAttrString(spec, "name");
@@ -51008,7 +49460,7 @@ bad:
 }
 
 
-static int __pyx_pymod_exec_pywrapfst(PyObject *__pyx_pyinit_module)
+static CYTHON_SMALL_CODE int __pyx_pymod_exec_pywrapfst(PyObject *__pyx_pyinit_module)
 #endif
 #endif
 {
@@ -51016,11 +49468,14 @@ static int __pyx_pymod_exec_pywrapfst(PyObject *__pyx_pyinit_module)
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  __pyx_t_10basictypes_int64 __pyx_t_5;
-  std::string __pyx_t_6;
+  std::string __pyx_t_5;
   __Pyx_RefNannyDeclarations
   #if CYTHON_PEP489_MULTI_PHASE_INIT
-  if (__pyx_m && __pyx_m == __pyx_pyinit_module) return 0;
+  if (__pyx_m) {
+    if (__pyx_m == __pyx_pyinit_module) return 0;
+    PyErr_SetString(PyExc_RuntimeError, "Module 'pywrapfst' has already been imported. Re-initialisation is not supported.");
+    return -1;
+  }
   #elif PY_MAJOR_VERSION >= 3
   if (__pyx_m) return __Pyx_NewRef(__pyx_m);
   #endif
@@ -51035,6 +49490,9 @@ if (!__Pyx_RefNanny) {
 #endif
   __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_pywrapfst(void)", 0);
   if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
+  #ifdef __Pxy_PyFrame_Initialize_Offsets
+  __Pxy_PyFrame_Initialize_Offsets();
+  #endif
   __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error)
   __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error)
   __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error)
@@ -51089,7 +49547,7 @@ if (!__Pyx_RefNanny) {
   if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   #endif
   if (__pyx_module_is_main_pywrapfst) {
-    if (PyObject_SetAttrString(__pyx_m, "__name__", __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
+    if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   }
   #if PY_MAJOR_VERSION >= 3
   {
@@ -51116,97 +49574,76 @@ if (!__Pyx_RefNanny) {
   if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error)
   #endif
 
-  /* "pywrapfst.pyx":107
+  /* "pywrapfst.pyx":98
  * 
  * # Python imports.
- * import atexit             # <<<<<<<<<<<<<<
- * import numbers
- * import subprocess
- */
-  __pyx_t_1 = __Pyx_Import(__pyx_n_s_atexit, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 107, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_atexit, __pyx_t_1) < 0) __PYX_ERR(0, 107, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-  /* "pywrapfst.pyx":108
- * # Python imports.
- * import atexit
  * import numbers             # <<<<<<<<<<<<<<
  * import subprocess
  * import logging
  */
-  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numbers, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 108, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numbers, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 98, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_numbers, __pyx_t_1) < 0) __PYX_ERR(0, 108, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_numbers, __pyx_t_1) < 0) __PYX_ERR(0, 98, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":109
- * import atexit
+  /* "pywrapfst.pyx":99
+ * # Python imports.
  * import numbers
  * import subprocess             # <<<<<<<<<<<<<<
  * import logging
  * 
  */
-  __pyx_t_1 = __Pyx_Import(__pyx_n_s_subprocess, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 109, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_Import(__pyx_n_s_subprocess, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 99, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_subprocess, __pyx_t_1) < 0) __PYX_ERR(0, 109, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_subprocess, __pyx_t_1) < 0) __PYX_ERR(0, 99, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":110
+  /* "pywrapfst.pyx":100
  * import numbers
  * import subprocess
  * import logging             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_1 = __Pyx_Import(__pyx_n_s_logging, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 110, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_Import(__pyx_n_s_logging, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 100, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_logging, __pyx_t_1) < 0) __PYX_ERR(0, 110, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_logging, __pyx_t_1) < 0) __PYX_ERR(0, 100, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":115
- * # TODO(kbg): Figure out how to access static class variables so I don't have
- * # to do it this way.
- * kNoSymbol = -1             # <<<<<<<<<<<<<<
- * 
- * 
- */
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_kNoSymbol, __pyx_int_neg_1) < 0) __PYX_ERR(0, 115, __pyx_L1_error)
-
-  /* "pywrapfst.pyx":121
+  /* "pywrapfst.pyx":106
  * 
  * 
  * class FstError(Exception):             # <<<<<<<<<<<<<<
  * 
  *   pass
  */
-  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 121, __pyx_L1_error)
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 106, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_INCREF(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0])));
   __Pyx_GIVEREF(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0])));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0])));
-  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 121, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 106, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_FstError, __pyx_n_s_FstError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 121, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_FstError, __pyx_n_s_FstError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 106, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_FstError, __pyx_t_1, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 121, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_FstError, __pyx_t_1, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 106, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstError, __pyx_t_4) < 0) __PYX_ERR(0, 121, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstError, __pyx_t_4) < 0) __PYX_ERR(0, 106, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":126
+  /* "pywrapfst.pyx":111
  * 
  * 
  * class FstArgError(FstError, ValueError):             # <<<<<<<<<<<<<<
  * 
  *   pass
  */
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 126, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_FstError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 111, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 126, __pyx_L1_error)
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 111, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
@@ -51214,28 +49651,28 @@ if (!__Pyx_RefNanny) {
   __Pyx_GIVEREF(__pyx_builtin_ValueError);
   PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_builtin_ValueError);
   __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 126, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 111, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_FstArgError, __pyx_n_s_FstArgError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 126, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_FstArgError, __pyx_n_s_FstArgError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 111, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_FstArgError, __pyx_t_2, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 126, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_FstArgError, __pyx_t_2, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 111, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstArgError, __pyx_t_4) < 0) __PYX_ERR(0, 126, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstArgError, __pyx_t_4) < 0) __PYX_ERR(0, 111, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":131
+  /* "pywrapfst.pyx":116
  * 
  * 
  * class FstBadWeightError(FstError, ValueError):             # <<<<<<<<<<<<<<
  * 
  *   pass
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 131, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 116, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 131, __pyx_L1_error)
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 116, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_2);
   PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
@@ -51243,28 +49680,28 @@ if (!__Pyx_RefNanny) {
   __Pyx_GIVEREF(__pyx_builtin_ValueError);
   PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_builtin_ValueError);
   __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 131, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 116, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_FstBadWeightError, __pyx_n_s_FstBadWeightError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 131, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_FstBadWeightError, __pyx_n_s_FstBadWeightError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 116, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_FstBadWeightError, __pyx_t_1, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 131, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_FstBadWeightError, __pyx_t_1, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 116, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstBadWeightError, __pyx_t_4) < 0) __PYX_ERR(0, 131, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstBadWeightError, __pyx_t_4) < 0) __PYX_ERR(0, 116, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":136
+  /* "pywrapfst.pyx":121
  * 
  * 
  * class FstDeletedConstructorError(FstError, RuntimeError):             # <<<<<<<<<<<<<<
  * 
  *   pass
  */
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 136, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_FstError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 121, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 136, __pyx_L1_error)
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 121, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
@@ -51272,28 +49709,28 @@ if (!__Pyx_RefNanny) {
   __Pyx_GIVEREF(__pyx_builtin_RuntimeError);
   PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_builtin_RuntimeError);
   __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 136, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 121, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_FstDeletedConstructorError, __pyx_n_s_FstDeletedConstructorError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 136, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_FstDeletedConstructorError, __pyx_n_s_FstDeletedConstructorError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 121, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_FstDeletedConstructorError, __pyx_t_2, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 136, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_FstDeletedConstructorError, __pyx_t_2, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 121, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstDeletedConstructorError, __pyx_t_4) < 0) __PYX_ERR(0, 136, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstDeletedConstructorError, __pyx_t_4) < 0) __PYX_ERR(0, 121, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":141
+  /* "pywrapfst.pyx":126
  * 
  * 
  * class FstIndexError(FstError, IndexError):             # <<<<<<<<<<<<<<
  * 
  *   pass
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 141, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 126, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 141, __pyx_L1_error)
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 126, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_2);
   PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
@@ -51301,28 +49738,28 @@ if (!__Pyx_RefNanny) {
   __Pyx_GIVEREF(__pyx_builtin_IndexError);
   PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_builtin_IndexError);
   __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 141, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 126, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_FstIndexError, __pyx_n_s_FstIndexError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 141, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_FstIndexError, __pyx_n_s_FstIndexError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 126, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_FstIndexError, __pyx_t_1, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 141, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_FstIndexError, __pyx_t_1, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 126, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstIndexError, __pyx_t_4) < 0) __PYX_ERR(0, 141, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstIndexError, __pyx_t_4) < 0) __PYX_ERR(0, 126, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":146
+  /* "pywrapfst.pyx":131
  * 
  * 
  * class FstIOError(FstError, IOError):             # <<<<<<<<<<<<<<
  * 
  *   pass
  */
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 146, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_FstError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 131, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 146, __pyx_L1_error)
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 131, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
@@ -51330,28 +49767,28 @@ if (!__Pyx_RefNanny) {
   __Pyx_GIVEREF(__pyx_builtin_IOError);
   PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_builtin_IOError);
   __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 146, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 131, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_FstIOError, __pyx_n_s_FstIOError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 146, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_FstIOError, __pyx_n_s_FstIOError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 131, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_FstIOError, __pyx_t_2, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 146, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_FstIOError, __pyx_t_2, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 131, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstIOError, __pyx_t_4) < 0) __PYX_ERR(0, 146, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstIOError, __pyx_t_4) < 0) __PYX_ERR(0, 131, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":151
+  /* "pywrapfst.pyx":136
  * 
  * 
  * class FstOpError(FstError, RuntimeError):             # <<<<<<<<<<<<<<
  * 
  *   pass
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_FstError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 151, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_FstError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 136, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error)
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 136, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_2);
   PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
@@ -51359,1726 +49796,1668 @@ if (!__Pyx_RefNanny) {
   __Pyx_GIVEREF(__pyx_builtin_RuntimeError);
   PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_builtin_RuntimeError);
   __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 151, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 136, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_FstOpError, __pyx_n_s_FstOpError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 151, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_FstOpError, __pyx_n_s_FstOpError, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, (PyObject *) NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 136, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_FstOpError, __pyx_t_1, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 151, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_FstOpError, __pyx_t_1, __pyx_t_3, NULL, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 136, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstOpError, __pyx_t_4) < 0) __PYX_ERR(0, 151, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FstOpError, __pyx_t_4) < 0) __PYX_ERR(0, 136, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":406
+  /* "pywrapfst.pyx":391
  * 
  *   @classmethod
  *   def Zero(cls, weight_type):             # <<<<<<<<<<<<<<
  *     """
  *     Weight.Zero(weight_type)
  */
-  __pyx_t_1 = __Pyx_GetNameInClass((PyObject *)__pyx_ptype_9pywrapfst_Weight, __pyx_n_s_Zero); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 406, __pyx_L1_error)
+  __Pyx_GetNameInClass(__pyx_t_1, (PyObject *)__pyx_ptype_9pywrapfst_Weight, __pyx_n_s_Zero); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 391, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
 
-  /* "pywrapfst.pyx":405
+  /* "pywrapfst.pyx":390
  *   # C++ part out-of-class and then call it from within.
  * 
  *   @classmethod             # <<<<<<<<<<<<<<
  *   def Zero(cls, weight_type):
  *     """
  */
-  __pyx_t_2 = __Pyx_Method_ClassMethod(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 405, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_Method_ClassMethod(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 390, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_Weight->tp_dict, __pyx_n_s_Zero, __pyx_t_2) < 0) __PYX_ERR(0, 406, __pyx_L1_error)
+  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_Weight->tp_dict, __pyx_n_s_Zero, __pyx_t_2) < 0) __PYX_ERR(0, 391, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   PyType_Modified(__pyx_ptype_9pywrapfst_Weight);
 
-  /* "pywrapfst.pyx":415
+  /* "pywrapfst.pyx":400
  * 
  *   @classmethod
  *   def One(cls, weight_type):             # <<<<<<<<<<<<<<
  *     """
  *     Weight.One(weight_type)
  */
-  __pyx_t_2 = __Pyx_GetNameInClass((PyObject *)__pyx_ptype_9pywrapfst_Weight, __pyx_n_s_One); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 415, __pyx_L1_error)
+  __Pyx_GetNameInClass(__pyx_t_2, (PyObject *)__pyx_ptype_9pywrapfst_Weight, __pyx_n_s_One); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 400, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
 
-  /* "pywrapfst.pyx":414
+  /* "pywrapfst.pyx":399
  *     return _Zero(weight_type)
  * 
  *   @classmethod             # <<<<<<<<<<<<<<
  *   def One(cls, weight_type):
  *     """
  */
-  __pyx_t_1 = __Pyx_Method_ClassMethod(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 414, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_Method_ClassMethod(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 399, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_Weight->tp_dict, __pyx_n_s_One, __pyx_t_1) < 0) __PYX_ERR(0, 415, __pyx_L1_error)
+  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_Weight->tp_dict, __pyx_n_s_One, __pyx_t_1) < 0) __PYX_ERR(0, 400, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   PyType_Modified(__pyx_ptype_9pywrapfst_Weight);
 
-  /* "pywrapfst.pyx":424
+  /* "pywrapfst.pyx":409
  * 
  *   @classmethod
  *   def NoWeight(cls, weight_type):             # <<<<<<<<<<<<<<
  *     """
  *     Weight.NoWeight(weight_type)
  */
-  __pyx_t_1 = __Pyx_GetNameInClass((PyObject *)__pyx_ptype_9pywrapfst_Weight, __pyx_n_s_NoWeight); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 424, __pyx_L1_error)
+  __Pyx_GetNameInClass(__pyx_t_1, (PyObject *)__pyx_ptype_9pywrapfst_Weight, __pyx_n_s_NoWeight); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 409, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
 
-  /* "pywrapfst.pyx":423
+  /* "pywrapfst.pyx":408
  *     return _One(weight_type)
  * 
  *   @classmethod             # <<<<<<<<<<<<<<
  *   def NoWeight(cls, weight_type):
  *     """
  */
-  __pyx_t_2 = __Pyx_Method_ClassMethod(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 423, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_Method_ClassMethod(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 408, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_Weight->tp_dict, __pyx_n_s_NoWeight, __pyx_t_2) < 0) __PYX_ERR(0, 424, __pyx_L1_error)
+  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_Weight->tp_dict, __pyx_n_s_NoWeight, __pyx_t_2) < 0) __PYX_ERR(0, 409, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   PyType_Modified(__pyx_ptype_9pywrapfst_Weight);
 
-  /* "pywrapfst.pyx":456
+  /* "pywrapfst.pyx":441
  * 
  * 
  * def plus(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
  *   """
  *   plus(lhs, rhs)
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_1plus, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 456, __pyx_L1_error)
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_1plus, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 441, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_plus, __pyx_t_2) < 0) __PYX_ERR(0, 456, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_plus, __pyx_t_2) < 0) __PYX_ERR(0, 441, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":488
+  /* "pywrapfst.pyx":473
  * 
  * 
  * def times(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
  *   """
  *   times(lhs, rhs)
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_3times, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 488, __pyx_L1_error)
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_3times, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 473, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_times, __pyx_t_2) < 0) __PYX_ERR(0, 488, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_times, __pyx_t_2) < 0) __PYX_ERR(0, 473, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":520
+  /* "pywrapfst.pyx":505
  * 
  * 
  * def divide(Weight lhs, Weight rhs):             # <<<<<<<<<<<<<<
  *   """
  *   divide(lhs, rhs)
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_5divide, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 520, __pyx_L1_error)
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_5divide, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 505, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_divide, __pyx_t_2) < 0) __PYX_ERR(0, 520, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_divide, __pyx_t_2) < 0) __PYX_ERR(0, 505, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":553
+  /* "pywrapfst.pyx":538
  * 
  * 
  * def power(Weight w, size_t n):             # <<<<<<<<<<<<<<
  *   """
  *   power(lhs, rhs)
  */
-  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_7power, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 553, __pyx_L1_error)
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_7power, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 538, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_power, __pyx_t_2) < 0) __PYX_ERR(0, 553, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_power, __pyx_t_2) < 0) __PYX_ERR(0, 538, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "pywrapfst.pyx":889
+  /* "pywrapfst.pyx":898
  *   """
  * 
- *   cpdef int64 add_symbol(self, symbol, int64 key=kNoSymbol):             # <<<<<<<<<<<<<<
+ *   cpdef int64 add_symbol(self, symbol, int64 key=fst.kNoSymbol):             # <<<<<<<<<<<<<<
  *     """
  *     add_symbol(self, symbol, key=NO_SYMBOL)
  */
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_kNoSymbol); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 889, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 889, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_k__13 = __pyx_t_5;
-  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_kNoSymbol); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 889, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_5 = __Pyx_PyInt_As_int64_t(__pyx_t_2); if (unlikely((__pyx_t_5 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 889, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_k__13 = __pyx_t_5;
+  __pyx_k__3 = fst::kNoSymbol;
+  __pyx_k__3 = fst::kNoSymbol;
 
-  /* "pywrapfst.pyx":966
+  /* "pywrapfst.pyx":975
  * 
  *   @classmethod
  *   def read(cls, filename):             # <<<<<<<<<<<<<<
  *     """
  *     SymbolTable.read(filename)
  */
-  __pyx_t_2 = __Pyx_GetNameInClass((PyObject *)__pyx_ptype_9pywrapfst_SymbolTable, __pyx_n_s_read); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 966, __pyx_L1_error)
+  __Pyx_GetNameInClass(__pyx_t_2, (PyObject *)__pyx_ptype_9pywrapfst_SymbolTable, __pyx_n_s_read); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 975, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
 
-  /* "pywrapfst.pyx":965
+  /* "pywrapfst.pyx":974
  *     self._smart_table.reset(self._table)
  * 
  *   @classmethod             # <<<<<<<<<<<<<<
  *   def read(cls, filename):
  *     """
  */
-  __pyx_t_1 = __Pyx_Method_ClassMethod(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 965, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_Method_ClassMethod(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 974, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_SymbolTable->tp_dict, __pyx_n_s_read, __pyx_t_1) < 0) __PYX_ERR(0, 966, __pyx_L1_error)
+  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_SymbolTable->tp_dict, __pyx_n_s_read, __pyx_t_1) < 0) __PYX_ERR(0, 975, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   PyType_Modified(__pyx_ptype_9pywrapfst_SymbolTable);
 
-  /* "pywrapfst.pyx":988
+  /* "pywrapfst.pyx":998
  * 
  *   @classmethod
  *   def read_text(cls, filename, bool allow_negative_labels=False):             # <<<<<<<<<<<<<<
  *     """
  *     SymbolTable.read_text(filename)
  */
-  __pyx_t_1 = __Pyx_GetNameInClass((PyObject *)__pyx_ptype_9pywrapfst_SymbolTable, __pyx_n_s_read_text); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 988, __pyx_L1_error)
+  __Pyx_GetNameInClass(__pyx_t_1, (PyObject *)__pyx_ptype_9pywrapfst_SymbolTable, __pyx_n_s_read_text); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 998, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
 
-  /* "pywrapfst.pyx":987
- *     return _init_SymbolTable(tsyms)
+  /* "pywrapfst.pyx":997
+ *     return _init_SymbolTable(syms.release())
  * 
  *   @classmethod             # <<<<<<<<<<<<<<
  *   def read_text(cls, filename, bool allow_negative_labels=False):
  *     """
  */
-  __pyx_t_2 = __Pyx_Method_ClassMethod(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 987, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_Method_ClassMethod(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 997, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_SymbolTable->tp_dict, __pyx_n_s_read_text, __pyx_t_2) < 0) __PYX_ERR(0, 988, __pyx_L1_error)
+  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_SymbolTable->tp_dict, __pyx_n_s_read_text, __pyx_t_2) < 0) __PYX_ERR(0, 998, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   PyType_Modified(__pyx_ptype_9pywrapfst_SymbolTable);
 
-  /* "pywrapfst.pyx":1015
+  /* "pywrapfst.pyx":1025
  * 
  *   @classmethod
  *   def read_fst(cls, filename, bool input_table):             # <<<<<<<<<<<<<<
  *     """
  *     SymbolTable.read_fst(filename, input_table)
  */
-  __pyx_t_2 = __Pyx_GetNameInClass((PyObject *)__pyx_ptype_9pywrapfst_SymbolTable, __pyx_n_s_read_fst); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1015, __pyx_L1_error)
+  __Pyx_GetNameInClass(__pyx_t_2, (PyObject *)__pyx_ptype_9pywrapfst_SymbolTable, __pyx_n_s_read_fst); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1025, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
 
-  /* "pywrapfst.pyx":1014
- *     return _init_SymbolTable(tsyms)
+  /* "pywrapfst.pyx":1024
+ *     return _init_SymbolTable(syms.release())
  * 
  *   @classmethod             # <<<<<<<<<<<<<<
  *   def read_fst(cls, filename, bool input_table):
  *     """
  */
-  __pyx_t_1 = __Pyx_Method_ClassMethod(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1014, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_Method_ClassMethod(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1024, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_SymbolTable->tp_dict, __pyx_n_s_read_fst, __pyx_t_1) < 0) __PYX_ERR(0, 1015, __pyx_L1_error)
+  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_SymbolTable->tp_dict, __pyx_n_s_read_fst, __pyx_t_1) < 0) __PYX_ERR(0, 1025, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   PyType_Modified(__pyx_ptype_9pywrapfst_SymbolTable);
 
-  /* "pywrapfst.pyx":2064
+  /* "pywrapfst.pyx":2086
  *     return self
  * 
  *   cdef void _minimize(self, float delta=fst.kShortestDelta,             # <<<<<<<<<<<<<<
  *                       bool allow_nondet=False) except *:
  *     # This runs in-place when the second argument is null.
  */
-  __pyx_k__35 = fst::kShortestDelta;
+  __pyx_k__11 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":2070
+  /* "pywrapfst.pyx":2092
  *     self._check_mutating_imethod()
  * 
  *   def minimize(self, float delta=fst.kShortestDelta, bool allow_nondet=False):             # <<<<<<<<<<<<<<
  *     """
  *     minimize(self, delta=1e-6, allow_nondet=False)
  */
-  __pyx_k__36 = fst::kShortestDelta;
+  __pyx_k__12 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":2170
+  /* "pywrapfst.pyx":2192
  *     return self
  * 
  *   cdef void _prune(self, float delta=fst.kDelta, int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                    weight=None) except *:
  *     # Threshold is set to semiring Zero (no pruning) if no weight is specified.
  */
-  __pyx_k__37 = fst::kDelta;
-  __pyx_k__38 = fst::kNoStateId;
+  __pyx_k__13 = fst::kDelta;
+  __pyx_k__14 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":2179
+  /* "pywrapfst.pyx":2201
  * 
  *   def prune(self,
  *             float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *             int64 nstate=fst.kNoStateId,
  *             weight=None):
  */
-  __pyx_k__39 = fst::kDelta;
+  __pyx_k__15 = fst::kDelta;
 
-  /* "pywrapfst.pyx":2180
+  /* "pywrapfst.pyx":2202
  *   def prune(self,
  *             float delta=fst.kDelta,
  *             int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *             weight=None):
  *     """
  */
-  __pyx_k__40 = fst::kNoStateId;
+  __pyx_k__16 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":2207
+  /* "pywrapfst.pyx":2229
  * 
  *   cdef void _push(self,
  *                   float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                   bool remove_total_weight=False,
  *                   bool to_final=False) except *:
  */
-  __pyx_k__41 = fst::kDelta;
+  __pyx_k__17 = fst::kDelta;
 
-  /* "pywrapfst.pyx":2215
+  /* "pywrapfst.pyx":2237
  * 
  *   def push(self,
  *            float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *            bool remove_total_weight=False,
  *            bool to_final=False):
  */
-  __pyx_k__42 = fst::kDelta;
+  __pyx_k__18 = fst::kDelta;
 
-  /* "pywrapfst.pyx":2452
+  /* "pywrapfst.pyx":2474
  *                        bool connect=True,
  *                        weight=None,
  *                        int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                        float delta=fst.kShortestDelta) except *:
  *     cdef fst.WeightClass wc = _get_WeightClass_or_Zero(self.weight_type(),
  */
-  __pyx_k__46 = fst::kNoStateId;
+  __pyx_k__19 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":2453
+  /* "pywrapfst.pyx":2475
  *                        weight=None,
  *                        int64 nstate=fst.kNoStateId,
  *                        float delta=fst.kShortestDelta) except *:             # <<<<<<<<<<<<<<
  *     cdef fst.WeightClass wc = _get_WeightClass_or_Zero(self.weight_type(),
  *                                                        weight)
  */
-  __pyx_k__47 = fst::kShortestDelta;
+  __pyx_k__20 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":2466
+  /* "pywrapfst.pyx":2488
  *                 bool connect=True,
  *                 weight=None,
  *                 int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                 float delta=fst.kShortestDelta):
  *     """
  */
-  __pyx_k__48 = fst::kNoStateId;
+  __pyx_k__21 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":2467
+  /* "pywrapfst.pyx":2489
  *                 weight=None,
  *                 int64 nstate=fst.kNoStateId,
  *                 float delta=fst.kShortestDelta):             # <<<<<<<<<<<<<<
  *     """
  *     rmepsilon(self, queue_type="auto", connect=True, weight=None,
  */
-  __pyx_k__49 = fst::kShortestDelta;
+  __pyx_k__22 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":2742
+  /* "pywrapfst.pyx":2762
  * 
  * 
  * class Fst(object):             # <<<<<<<<<<<<<<
  * 
  *    """
  */
-  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_tuple__107); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2742, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_tuple__68); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2762, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_tuple__107, __pyx_n_s_Fst, __pyx_n_s_Fst, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, __pyx_kp_s_Fst_arc_type_standard_Construct); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2742, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_tuple__68, __pyx_n_s_Fst_2, __pyx_n_s_Fst_2, (PyObject *) NULL, __pyx_n_s_pywrapfst_2, __pyx_kp_s_Fst_arc_type_standard_Construct); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2762, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
 
-  /* "pywrapfst.pyx":2759
+  /* "pywrapfst.pyx":2779
  *    """
  * 
  *    def __new__(cls, arc_type=b"standard"):             # <<<<<<<<<<<<<<
  *     return _create_Fst(arc_type)
  * 
  */
-  __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_9pywrapfst_3Fst_1__new__, __Pyx_CYFUNCTION_STATICMETHOD, __pyx_n_s_Fst___new, NULL, __pyx_n_s_pywrapfst_2, __pyx_d, ((PyObject *)__pyx_codeobj__109)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2759, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_9pywrapfst_3Fst_1__new__, __Pyx_CYFUNCTION_STATICMETHOD, __pyx_n_s_Fst___new, NULL, __pyx_n_s_pywrapfst_2, __pyx_d, ((PyObject *)__pyx_codeobj__70)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2779, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_3, __pyx_tuple__110);
-  if (__Pyx_SetNameInClass(__pyx_t_2, __pyx_n_s_new, __pyx_t_3) < 0) __PYX_ERR(0, 2759, __pyx_L1_error)
+  __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_3, __pyx_tuple__71);
+  if (__Pyx_SetNameInClass(__pyx_t_2, __pyx_n_s_new, __pyx_t_3) < 0) __PYX_ERR(0, 2779, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "pywrapfst.pyx":2763
+  /* "pywrapfst.pyx":2783
  * 
  *    @staticmethod
  *    def read(filename):             # <<<<<<<<<<<<<<
  *      """
  *      read(filename):
  */
-  __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_9pywrapfst_3Fst_3read, __Pyx_CYFUNCTION_STATICMETHOD, __pyx_n_s_Fst_read, NULL, __pyx_n_s_pywrapfst_2, __pyx_d, ((PyObject *)__pyx_codeobj__112)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2763, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_CyFunction_NewEx(&__pyx_mdef_9pywrapfst_3Fst_3read, __Pyx_CYFUNCTION_STATICMETHOD, __pyx_n_s_Fst_read, NULL, __pyx_n_s_pywrapfst_2, __pyx_d, ((PyObject *)__pyx_codeobj__73)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2783, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
 
-  /* "pywrapfst.pyx":2762
+  /* "pywrapfst.pyx":2782
  *     return _create_Fst(arc_type)
  * 
  *    @staticmethod             # <<<<<<<<<<<<<<
  *    def read(filename):
  *      """
  */
-  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_staticmethod, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2762, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_staticmethod, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2782, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (__Pyx_SetNameInClass(__pyx_t_2, __pyx_n_s_read, __pyx_t_4) < 0) __PYX_ERR(0, 2763, __pyx_L1_error)
+  if (__Pyx_SetNameInClass(__pyx_t_2, __pyx_n_s_read, __pyx_t_4) < 0) __PYX_ERR(0, 2783, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-  /* "pywrapfst.pyx":2781
+  /* "pywrapfst.pyx":2801
  * 
  *    @staticmethod
  *    def read_from_string(state):             # <<<<<<<<<<<<<<
  *      """
  *      read_from_string(string, fst_type=None)
  */
-  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_9pywrapfst_3Fst_5read_from_string, __Pyx_CYFUNCTION_STATICMETHOD, __pyx_n_s_Fst_read_from_string, NULL, __pyx_n_s_pywrapfst_2, __pyx_d, ((PyObject *)__pyx_codeobj__114)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2781, __pyx_L1_error)
+  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_9pywrapfst_3Fst_5read_from_string, __Pyx_CYFUNCTION_STATICMETHOD, __pyx_n_s_Fst_read_from_string, NULL, __pyx_n_s_pywrapfst_2, __pyx_d, ((PyObject *)__pyx_codeobj__75)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2801, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_4);
 
-  /* "pywrapfst.pyx":2780
+  /* "pywrapfst.pyx":2800
  *      return _read(filename)
  * 
  *    @staticmethod             # <<<<<<<<<<<<<<
  *    def read_from_string(state):
  *      """
  */
-  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_staticmethod, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2780, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_staticmethod, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2800, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (__Pyx_SetNameInClass(__pyx_t_2, __pyx_n_s_read_from_string_2, __pyx_t_3) < 0) __PYX_ERR(0, 2781, __pyx_L1_error)
+  if (__Pyx_SetNameInClass(__pyx_t_2, __pyx_n_s_read_from_string, __pyx_t_3) < 0) __PYX_ERR(0, 2801, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "pywrapfst.pyx":2742
+  /* "pywrapfst.pyx":2762
  * 
  * 
  * class Fst(object):             # <<<<<<<<<<<<<<
  * 
  *    """
  */
-  __pyx_t_3 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_Fst, __pyx_tuple__107, __pyx_t_2, NULL, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2742, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_Fst_2, __pyx_tuple__68, __pyx_t_2, NULL, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2762, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_Fst, __pyx_t_3) < 0) __PYX_ERR(0, 2742, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_Fst_2, __pyx_t_3) < 0) __PYX_ERR(0, 2762, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2805
+  /* "pywrapfst.pyx":2825
  * 
  * 
  * NO_LABEL = fst.kNoLabel             # <<<<<<<<<<<<<<
  * NO_STATE_ID = fst.kNoStateId
- * # TODO(kbg): Figure out how to access static class variables so I don't have
+ * NO_SYMBOL = fst.kNoSymbol
  */
-  __pyx_t_1 = __Pyx_PyInt_From_int(fst::kNoLabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2805, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int(fst::kNoLabel); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2825, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_LABEL, __pyx_t_1) < 0) __PYX_ERR(0, 2805, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_LABEL, __pyx_t_1) < 0) __PYX_ERR(0, 2825, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2806
+  /* "pywrapfst.pyx":2826
  * 
  * NO_LABEL = fst.kNoLabel
  * NO_STATE_ID = fst.kNoStateId             # <<<<<<<<<<<<<<
- * # TODO(kbg): Figure out how to access static class variables so I don't have
- * # to do it this way.
+ * NO_SYMBOL = fst.kNoSymbol
+ * 
  */
-  __pyx_t_1 = __Pyx_PyInt_From_int(fst::kNoStateId); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2806, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int(fst::kNoStateId); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2826, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_STATE_ID, __pyx_t_1) < 0) __PYX_ERR(0, 2806, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_STATE_ID, __pyx_t_1) < 0) __PYX_ERR(0, 2826, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2809
- * # TODO(kbg): Figure out how to access static class variables so I don't have
- * # to do it this way.
- * NO_SYMBOL = kNoSymbol             # <<<<<<<<<<<<<<
+  /* "pywrapfst.pyx":2827
+ * NO_LABEL = fst.kNoLabel
+ * NO_STATE_ID = fst.kNoStateId
+ * NO_SYMBOL = fst.kNoSymbol             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_kNoSymbol); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2809, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(fst::kNoSymbol); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2827, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_SYMBOL, __pyx_t_1) < 0) __PYX_ERR(0, 2809, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_SYMBOL, __pyx_t_1) < 0) __PYX_ERR(0, 2827, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2815
+  /* "pywrapfst.pyx":2833
  * 
  * 
  * EXPANDED = fst.kExpanded             # <<<<<<<<<<<<<<
  * MUTABLE = fst.kMutable
  * ERROR = fst.kError
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kExpanded); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2815, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kExpanded); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2833, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_EXPANDED, __pyx_t_1) < 0) __PYX_ERR(0, 2815, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_EXPANDED, __pyx_t_1) < 0) __PYX_ERR(0, 2833, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2816
+  /* "pywrapfst.pyx":2834
  * 
  * EXPANDED = fst.kExpanded
  * MUTABLE = fst.kMutable             # <<<<<<<<<<<<<<
  * ERROR = fst.kError
  * ACCEPTOR = fst.kAcceptor
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kMutable); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2816, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kMutable); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2834, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_MUTABLE, __pyx_t_1) < 0) __PYX_ERR(0, 2816, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_MUTABLE, __pyx_t_1) < 0) __PYX_ERR(0, 2834, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2817
+  /* "pywrapfst.pyx":2835
  * EXPANDED = fst.kExpanded
  * MUTABLE = fst.kMutable
  * ERROR = fst.kError             # <<<<<<<<<<<<<<
  * ACCEPTOR = fst.kAcceptor
  * NOT_ACCEPTOR = fst.kNotAcceptor
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2817, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2835, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ERROR, __pyx_t_1) < 0) __PYX_ERR(0, 2817, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ERROR, __pyx_t_1) < 0) __PYX_ERR(0, 2835, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2818
+  /* "pywrapfst.pyx":2836
  * MUTABLE = fst.kMutable
  * ERROR = fst.kError
  * ACCEPTOR = fst.kAcceptor             # <<<<<<<<<<<<<<
  * NOT_ACCEPTOR = fst.kNotAcceptor
  * I_DETERMINISTIC = fst.kIDeterministic
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAcceptor); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2818, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAcceptor); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2836, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ACCEPTOR, __pyx_t_1) < 0) __PYX_ERR(0, 2818, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ACCEPTOR, __pyx_t_1) < 0) __PYX_ERR(0, 2836, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2819
+  /* "pywrapfst.pyx":2837
  * ERROR = fst.kError
  * ACCEPTOR = fst.kAcceptor
  * NOT_ACCEPTOR = fst.kNotAcceptor             # <<<<<<<<<<<<<<
  * I_DETERMINISTIC = fst.kIDeterministic
  * NON_I_DETERMINISTIC = fst.kNonIDeterministic
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotAcceptor); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2819, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotAcceptor); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2837, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_ACCEPTOR, __pyx_t_1) < 0) __PYX_ERR(0, 2819, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_ACCEPTOR, __pyx_t_1) < 0) __PYX_ERR(0, 2837, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2820
+  /* "pywrapfst.pyx":2838
  * ACCEPTOR = fst.kAcceptor
  * NOT_ACCEPTOR = fst.kNotAcceptor
  * I_DETERMINISTIC = fst.kIDeterministic             # <<<<<<<<<<<<<<
  * NON_I_DETERMINISTIC = fst.kNonIDeterministic
  * O_DETERMINISTIC = fst.kODeterministic
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kIDeterministic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2820, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kIDeterministic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2838, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_I_DETERMINISTIC, __pyx_t_1) < 0) __PYX_ERR(0, 2820, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_I_DETERMINISTIC, __pyx_t_1) < 0) __PYX_ERR(0, 2838, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2821
+  /* "pywrapfst.pyx":2839
  * NOT_ACCEPTOR = fst.kNotAcceptor
  * I_DETERMINISTIC = fst.kIDeterministic
  * NON_I_DETERMINISTIC = fst.kNonIDeterministic             # <<<<<<<<<<<<<<
  * O_DETERMINISTIC = fst.kODeterministic
  * NON_O_DETERMINISTIC = fst.kNonODeterministic
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNonIDeterministic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2821, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNonIDeterministic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2839, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NON_I_DETERMINISTIC, __pyx_t_1) < 0) __PYX_ERR(0, 2821, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NON_I_DETERMINISTIC, __pyx_t_1) < 0) __PYX_ERR(0, 2839, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2822
+  /* "pywrapfst.pyx":2840
  * I_DETERMINISTIC = fst.kIDeterministic
  * NON_I_DETERMINISTIC = fst.kNonIDeterministic
  * O_DETERMINISTIC = fst.kODeterministic             # <<<<<<<<<<<<<<
  * NON_O_DETERMINISTIC = fst.kNonODeterministic
  * EPSILONS = fst.kEpsilons
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kODeterministic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2822, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kODeterministic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2840, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_O_DETERMINISTIC, __pyx_t_1) < 0) __PYX_ERR(0, 2822, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_O_DETERMINISTIC, __pyx_t_1) < 0) __PYX_ERR(0, 2840, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2823
+  /* "pywrapfst.pyx":2841
  * NON_I_DETERMINISTIC = fst.kNonIDeterministic
  * O_DETERMINISTIC = fst.kODeterministic
  * NON_O_DETERMINISTIC = fst.kNonODeterministic             # <<<<<<<<<<<<<<
  * EPSILONS = fst.kEpsilons
  * NO_EPSILONS = fst.kNoEpsilons
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNonODeterministic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2823, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNonODeterministic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2841, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NON_O_DETERMINISTIC, __pyx_t_1) < 0) __PYX_ERR(0, 2823, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NON_O_DETERMINISTIC, __pyx_t_1) < 0) __PYX_ERR(0, 2841, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2824
+  /* "pywrapfst.pyx":2842
  * O_DETERMINISTIC = fst.kODeterministic
  * NON_O_DETERMINISTIC = fst.kNonODeterministic
  * EPSILONS = fst.kEpsilons             # <<<<<<<<<<<<<<
  * NO_EPSILONS = fst.kNoEpsilons
  * I_EPSILONS = fst.kIEpsilons
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2824, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2842, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2824, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2842, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2825
+  /* "pywrapfst.pyx":2843
  * NON_O_DETERMINISTIC = fst.kNonODeterministic
  * EPSILONS = fst.kEpsilons
  * NO_EPSILONS = fst.kNoEpsilons             # <<<<<<<<<<<<<<
  * I_EPSILONS = fst.kIEpsilons
  * NO_I_EPSILONS = fst.kNoIEpsilons
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNoEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2825, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNoEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2843, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2825, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2843, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2826
+  /* "pywrapfst.pyx":2844
  * EPSILONS = fst.kEpsilons
  * NO_EPSILONS = fst.kNoEpsilons
  * I_EPSILONS = fst.kIEpsilons             # <<<<<<<<<<<<<<
  * NO_I_EPSILONS = fst.kNoIEpsilons
  * O_EPSILONS = fst.kOEpsilons
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kIEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2826, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kIEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2844, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_I_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2826, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_I_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2844, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2827
+  /* "pywrapfst.pyx":2845
  * NO_EPSILONS = fst.kNoEpsilons
  * I_EPSILONS = fst.kIEpsilons
  * NO_I_EPSILONS = fst.kNoIEpsilons             # <<<<<<<<<<<<<<
  * O_EPSILONS = fst.kOEpsilons
  * NO_O_EPSILONS = fst.kNoOEpsilons
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNoIEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2827, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNoIEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2845, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_I_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2827, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_I_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2845, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2828
+  /* "pywrapfst.pyx":2846
  * I_EPSILONS = fst.kIEpsilons
  * NO_I_EPSILONS = fst.kNoIEpsilons
  * O_EPSILONS = fst.kOEpsilons             # <<<<<<<<<<<<<<
  * NO_O_EPSILONS = fst.kNoOEpsilons
  * I_LABEL_SORTED = fst.kILabelSorted
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kOEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2828, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kOEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2846, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_O_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2828, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_O_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2846, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2829
+  /* "pywrapfst.pyx":2847
  * NO_I_EPSILONS = fst.kNoIEpsilons
  * O_EPSILONS = fst.kOEpsilons
  * NO_O_EPSILONS = fst.kNoOEpsilons             # <<<<<<<<<<<<<<
  * I_LABEL_SORTED = fst.kILabelSorted
  * NOT_I_LABEL_SORTED = fst.kNotILabelSorted
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNoOEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2829, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNoOEpsilons); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2847, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_O_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2829, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NO_O_EPSILONS, __pyx_t_1) < 0) __PYX_ERR(0, 2847, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2830
+  /* "pywrapfst.pyx":2848
  * O_EPSILONS = fst.kOEpsilons
  * NO_O_EPSILONS = fst.kNoOEpsilons
  * I_LABEL_SORTED = fst.kILabelSorted             # <<<<<<<<<<<<<<
  * NOT_I_LABEL_SORTED = fst.kNotILabelSorted
  * O_LABEL_SORTED = fst.kOLabelSorted
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kILabelSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2830, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kILabelSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2848, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_I_LABEL_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2830, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_I_LABEL_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2848, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2831
+  /* "pywrapfst.pyx":2849
  * NO_O_EPSILONS = fst.kNoOEpsilons
  * I_LABEL_SORTED = fst.kILabelSorted
  * NOT_I_LABEL_SORTED = fst.kNotILabelSorted             # <<<<<<<<<<<<<<
  * O_LABEL_SORTED = fst.kOLabelSorted
  * NOT_O_LABEL_SORTED = fst.kNotOLabelSorted
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotILabelSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2831, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotILabelSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2849, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_I_LABEL_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2831, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_I_LABEL_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2849, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2832
+  /* "pywrapfst.pyx":2850
  * I_LABEL_SORTED = fst.kILabelSorted
  * NOT_I_LABEL_SORTED = fst.kNotILabelSorted
  * O_LABEL_SORTED = fst.kOLabelSorted             # <<<<<<<<<<<<<<
  * NOT_O_LABEL_SORTED = fst.kNotOLabelSorted
  * WEIGHTED = fst.kWeighted
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kOLabelSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2832, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kOLabelSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2850, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_O_LABEL_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2832, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_O_LABEL_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2850, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2833
+  /* "pywrapfst.pyx":2851
  * NOT_I_LABEL_SORTED = fst.kNotILabelSorted
  * O_LABEL_SORTED = fst.kOLabelSorted
  * NOT_O_LABEL_SORTED = fst.kNotOLabelSorted             # <<<<<<<<<<<<<<
  * WEIGHTED = fst.kWeighted
  * UNWEIGHTED = fst.kUnweighted
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotOLabelSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2833, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotOLabelSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2851, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_O_LABEL_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2833, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_O_LABEL_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2851, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2834
+  /* "pywrapfst.pyx":2852
  * O_LABEL_SORTED = fst.kOLabelSorted
  * NOT_O_LABEL_SORTED = fst.kNotOLabelSorted
  * WEIGHTED = fst.kWeighted             # <<<<<<<<<<<<<<
  * UNWEIGHTED = fst.kUnweighted
  * CYCLIC = fst.kCyclic
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kWeighted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2834, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kWeighted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2852, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_WEIGHTED, __pyx_t_1) < 0) __PYX_ERR(0, 2834, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_WEIGHTED, __pyx_t_1) < 0) __PYX_ERR(0, 2852, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2835
+  /* "pywrapfst.pyx":2853
  * NOT_O_LABEL_SORTED = fst.kNotOLabelSorted
  * WEIGHTED = fst.kWeighted
  * UNWEIGHTED = fst.kUnweighted             # <<<<<<<<<<<<<<
  * CYCLIC = fst.kCyclic
  * ACYCLIC = fst.kAcyclic
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kUnweighted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2835, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kUnweighted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2853, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_UNWEIGHTED, __pyx_t_1) < 0) __PYX_ERR(0, 2835, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_UNWEIGHTED, __pyx_t_1) < 0) __PYX_ERR(0, 2853, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2836
+  /* "pywrapfst.pyx":2854
  * WEIGHTED = fst.kWeighted
  * UNWEIGHTED = fst.kUnweighted
  * CYCLIC = fst.kCyclic             # <<<<<<<<<<<<<<
  * ACYCLIC = fst.kAcyclic
  * INITIAL_CYCLIC = fst.kInitialCyclic
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kCyclic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2836, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kCyclic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2854, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_CYCLIC, __pyx_t_1) < 0) __PYX_ERR(0, 2836, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_CYCLIC, __pyx_t_1) < 0) __PYX_ERR(0, 2854, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2837
+  /* "pywrapfst.pyx":2855
  * UNWEIGHTED = fst.kUnweighted
  * CYCLIC = fst.kCyclic
  * ACYCLIC = fst.kAcyclic             # <<<<<<<<<<<<<<
  * INITIAL_CYCLIC = fst.kInitialCyclic
  * INITIAL_ACYCLIC = fst.kInitialAcyclic
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAcyclic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2837, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAcyclic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2855, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ACYCLIC, __pyx_t_1) < 0) __PYX_ERR(0, 2837, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ACYCLIC, __pyx_t_1) < 0) __PYX_ERR(0, 2855, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2838
+  /* "pywrapfst.pyx":2856
  * CYCLIC = fst.kCyclic
  * ACYCLIC = fst.kAcyclic
  * INITIAL_CYCLIC = fst.kInitialCyclic             # <<<<<<<<<<<<<<
  * INITIAL_ACYCLIC = fst.kInitialAcyclic
  * TOP_SORTED = fst.kTopSorted
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kInitialCyclic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2838, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kInitialCyclic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2856, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_INITIAL_CYCLIC, __pyx_t_1) < 0) __PYX_ERR(0, 2838, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_INITIAL_CYCLIC, __pyx_t_1) < 0) __PYX_ERR(0, 2856, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2839
+  /* "pywrapfst.pyx":2857
  * ACYCLIC = fst.kAcyclic
  * INITIAL_CYCLIC = fst.kInitialCyclic
  * INITIAL_ACYCLIC = fst.kInitialAcyclic             # <<<<<<<<<<<<<<
  * TOP_SORTED = fst.kTopSorted
  * NOT_TOP_SORTED = fst.kNotTopSorted
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kInitialAcyclic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2839, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kInitialAcyclic); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2857, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_INITIAL_ACYCLIC, __pyx_t_1) < 0) __PYX_ERR(0, 2839, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_INITIAL_ACYCLIC, __pyx_t_1) < 0) __PYX_ERR(0, 2857, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2840
+  /* "pywrapfst.pyx":2858
  * INITIAL_CYCLIC = fst.kInitialCyclic
  * INITIAL_ACYCLIC = fst.kInitialAcyclic
  * TOP_SORTED = fst.kTopSorted             # <<<<<<<<<<<<<<
  * NOT_TOP_SORTED = fst.kNotTopSorted
  * ACCESSIBLE = fst.kAccessible
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kTopSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2840, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kTopSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2858, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_TOP_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2840, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_TOP_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2858, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2841
+  /* "pywrapfst.pyx":2859
  * INITIAL_ACYCLIC = fst.kInitialAcyclic
  * TOP_SORTED = fst.kTopSorted
  * NOT_TOP_SORTED = fst.kNotTopSorted             # <<<<<<<<<<<<<<
  * ACCESSIBLE = fst.kAccessible
  * NOT_ACCESSIBLE = fst.kNotAccessible
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotTopSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2841, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotTopSorted); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2859, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_TOP_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2841, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_TOP_SORTED, __pyx_t_1) < 0) __PYX_ERR(0, 2859, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2842
+  /* "pywrapfst.pyx":2860
  * TOP_SORTED = fst.kTopSorted
  * NOT_TOP_SORTED = fst.kNotTopSorted
  * ACCESSIBLE = fst.kAccessible             # <<<<<<<<<<<<<<
  * NOT_ACCESSIBLE = fst.kNotAccessible
  * COACCESSIBLE = fst.kCoAccessible
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAccessible); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2842, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAccessible); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2860, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ACCESSIBLE, __pyx_t_1) < 0) __PYX_ERR(0, 2842, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ACCESSIBLE, __pyx_t_1) < 0) __PYX_ERR(0, 2860, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2843
+  /* "pywrapfst.pyx":2861
  * NOT_TOP_SORTED = fst.kNotTopSorted
  * ACCESSIBLE = fst.kAccessible
  * NOT_ACCESSIBLE = fst.kNotAccessible             # <<<<<<<<<<<<<<
  * COACCESSIBLE = fst.kCoAccessible
  * NOT_COACCESSIBLE = fst.kNotCoAccessible
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotAccessible); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2843, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotAccessible); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2861, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_ACCESSIBLE, __pyx_t_1) < 0) __PYX_ERR(0, 2843, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_ACCESSIBLE, __pyx_t_1) < 0) __PYX_ERR(0, 2861, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2844
+  /* "pywrapfst.pyx":2862
  * ACCESSIBLE = fst.kAccessible
  * NOT_ACCESSIBLE = fst.kNotAccessible
  * COACCESSIBLE = fst.kCoAccessible             # <<<<<<<<<<<<<<
  * NOT_COACCESSIBLE = fst.kNotCoAccessible
  * STRING = fst.kString
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kCoAccessible); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2844, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kCoAccessible); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2862, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_COACCESSIBLE, __pyx_t_1) < 0) __PYX_ERR(0, 2844, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_COACCESSIBLE, __pyx_t_1) < 0) __PYX_ERR(0, 2862, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2845
+  /* "pywrapfst.pyx":2863
  * NOT_ACCESSIBLE = fst.kNotAccessible
  * COACCESSIBLE = fst.kCoAccessible
  * NOT_COACCESSIBLE = fst.kNotCoAccessible             # <<<<<<<<<<<<<<
  * STRING = fst.kString
  * NOT_STRING = fst.kNotString
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotCoAccessible); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2845, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotCoAccessible); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2863, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_COACCESSIBLE, __pyx_t_1) < 0) __PYX_ERR(0, 2845, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_COACCESSIBLE, __pyx_t_1) < 0) __PYX_ERR(0, 2863, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2846
+  /* "pywrapfst.pyx":2864
  * COACCESSIBLE = fst.kCoAccessible
  * NOT_COACCESSIBLE = fst.kNotCoAccessible
  * STRING = fst.kString             # <<<<<<<<<<<<<<
  * NOT_STRING = fst.kNotString
  * WEIGHTED_CYCLES = fst.kWeightedCycles
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kString); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2846, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kString); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2864, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_STRING, __pyx_t_1) < 0) __PYX_ERR(0, 2846, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_STRING, __pyx_t_1) < 0) __PYX_ERR(0, 2864, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2847
+  /* "pywrapfst.pyx":2865
  * NOT_COACCESSIBLE = fst.kNotCoAccessible
  * STRING = fst.kString
  * NOT_STRING = fst.kNotString             # <<<<<<<<<<<<<<
  * WEIGHTED_CYCLES = fst.kWeightedCycles
  * UNWEIGHTED_CYCLES = fst.kUnweightedCycles
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotString); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2847, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNotString); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2865, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_STRING, __pyx_t_1) < 0) __PYX_ERR(0, 2847, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NOT_STRING, __pyx_t_1) < 0) __PYX_ERR(0, 2865, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2848
+  /* "pywrapfst.pyx":2866
  * STRING = fst.kString
  * NOT_STRING = fst.kNotString
  * WEIGHTED_CYCLES = fst.kWeightedCycles             # <<<<<<<<<<<<<<
  * UNWEIGHTED_CYCLES = fst.kUnweightedCycles
  * NULL_PROPERTIES = fst.kNullProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kWeightedCycles); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2848, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kWeightedCycles); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2866, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_WEIGHTED_CYCLES, __pyx_t_1) < 0) __PYX_ERR(0, 2848, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_WEIGHTED_CYCLES, __pyx_t_1) < 0) __PYX_ERR(0, 2866, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2849
+  /* "pywrapfst.pyx":2867
  * NOT_STRING = fst.kNotString
  * WEIGHTED_CYCLES = fst.kWeightedCycles
  * UNWEIGHTED_CYCLES = fst.kUnweightedCycles             # <<<<<<<<<<<<<<
  * NULL_PROPERTIES = fst.kNullProperties
  * COPY_PROPERTIES = fst.kCopyProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kUnweightedCycles); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2849, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kUnweightedCycles); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2867, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_UNWEIGHTED_CYCLES, __pyx_t_1) < 0) __PYX_ERR(0, 2849, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_UNWEIGHTED_CYCLES, __pyx_t_1) < 0) __PYX_ERR(0, 2867, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2850
+  /* "pywrapfst.pyx":2868
  * WEIGHTED_CYCLES = fst.kWeightedCycles
  * UNWEIGHTED_CYCLES = fst.kUnweightedCycles
  * NULL_PROPERTIES = fst.kNullProperties             # <<<<<<<<<<<<<<
  * COPY_PROPERTIES = fst.kCopyProperties
  * INTRINSIC_PROPERTIES = fst.kIntrinsicProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNullProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2850, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNullProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2868, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NULL_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2850, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NULL_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2868, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2851
+  /* "pywrapfst.pyx":2869
  * UNWEIGHTED_CYCLES = fst.kUnweightedCycles
  * NULL_PROPERTIES = fst.kNullProperties
  * COPY_PROPERTIES = fst.kCopyProperties             # <<<<<<<<<<<<<<
  * INTRINSIC_PROPERTIES = fst.kIntrinsicProperties
  * EXTRINSIC_PROPERTIES = fst.kExtrinsicProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kCopyProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2851, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kCopyProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2869, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_COPY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2851, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_COPY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2869, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2852
+  /* "pywrapfst.pyx":2870
  * NULL_PROPERTIES = fst.kNullProperties
  * COPY_PROPERTIES = fst.kCopyProperties
  * INTRINSIC_PROPERTIES = fst.kIntrinsicProperties             # <<<<<<<<<<<<<<
  * EXTRINSIC_PROPERTIES = fst.kExtrinsicProperties
  * SET_START_PROPERTIES = fst.kSetStartProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kIntrinsicProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2852, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kIntrinsicProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2870, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_INTRINSIC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2852, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_INTRINSIC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2870, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2853
+  /* "pywrapfst.pyx":2871
  * COPY_PROPERTIES = fst.kCopyProperties
  * INTRINSIC_PROPERTIES = fst.kIntrinsicProperties
  * EXTRINSIC_PROPERTIES = fst.kExtrinsicProperties             # <<<<<<<<<<<<<<
  * SET_START_PROPERTIES = fst.kSetStartProperties
  * SET_FINAL_PROPERTIES = fst.kSetFinalProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kExtrinsicProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2853, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kExtrinsicProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2871, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_EXTRINSIC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2853, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_EXTRINSIC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2871, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2854
+  /* "pywrapfst.pyx":2872
  * INTRINSIC_PROPERTIES = fst.kIntrinsicProperties
  * EXTRINSIC_PROPERTIES = fst.kExtrinsicProperties
  * SET_START_PROPERTIES = fst.kSetStartProperties             # <<<<<<<<<<<<<<
  * SET_FINAL_PROPERTIES = fst.kSetFinalProperties
  * ADD_STATE_PROPERTIES = fst.kAddStateProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kSetStartProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2854, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kSetStartProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2872, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_SET_START_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2854, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_SET_START_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2872, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2855
+  /* "pywrapfst.pyx":2873
  * EXTRINSIC_PROPERTIES = fst.kExtrinsicProperties
  * SET_START_PROPERTIES = fst.kSetStartProperties
  * SET_FINAL_PROPERTIES = fst.kSetFinalProperties             # <<<<<<<<<<<<<<
  * ADD_STATE_PROPERTIES = fst.kAddStateProperties
  * ADD_ARC_PROPERTIES = fst.kAddArcProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kSetFinalProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2855, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kSetFinalProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2873, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_SET_FINAL_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2855, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_SET_FINAL_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2873, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2856
+  /* "pywrapfst.pyx":2874
  * SET_START_PROPERTIES = fst.kSetStartProperties
  * SET_FINAL_PROPERTIES = fst.kSetFinalProperties
  * ADD_STATE_PROPERTIES = fst.kAddStateProperties             # <<<<<<<<<<<<<<
  * ADD_ARC_PROPERTIES = fst.kAddArcProperties
  * SET_ARC_PROPERTIES = fst.kSetArcProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAddStateProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2856, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAddStateProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2874, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ADD_STATE_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2856, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ADD_STATE_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2874, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2857
+  /* "pywrapfst.pyx":2875
  * SET_FINAL_PROPERTIES = fst.kSetFinalProperties
  * ADD_STATE_PROPERTIES = fst.kAddStateProperties
  * ADD_ARC_PROPERTIES = fst.kAddArcProperties             # <<<<<<<<<<<<<<
  * SET_ARC_PROPERTIES = fst.kSetArcProperties
  * DELETE_STATE_PROPERTIES = fst.kDeleteStatesProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAddArcProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2857, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAddArcProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2875, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ADD_ARC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2857, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ADD_ARC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2875, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2858
+  /* "pywrapfst.pyx":2876
  * ADD_STATE_PROPERTIES = fst.kAddStateProperties
  * ADD_ARC_PROPERTIES = fst.kAddArcProperties
  * SET_ARC_PROPERTIES = fst.kSetArcProperties             # <<<<<<<<<<<<<<
  * DELETE_STATE_PROPERTIES = fst.kDeleteStatesProperties
  * DELETE_ARC_PROPERTIES = fst.kDeleteArcsProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kSetArcProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2858, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kSetArcProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2876, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_SET_ARC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2858, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_SET_ARC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2876, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2859
+  /* "pywrapfst.pyx":2877
  * ADD_ARC_PROPERTIES = fst.kAddArcProperties
  * SET_ARC_PROPERTIES = fst.kSetArcProperties
  * DELETE_STATE_PROPERTIES = fst.kDeleteStatesProperties             # <<<<<<<<<<<<<<
  * DELETE_ARC_PROPERTIES = fst.kDeleteArcsProperties
  * STATE_SORT_PROPERTIES = fst.kStateSortProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kDeleteStatesProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2859, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kDeleteStatesProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2877, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_DELETE_STATE_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2859, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_DELETE_STATE_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2877, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2860
+  /* "pywrapfst.pyx":2878
  * SET_ARC_PROPERTIES = fst.kSetArcProperties
  * DELETE_STATE_PROPERTIES = fst.kDeleteStatesProperties
  * DELETE_ARC_PROPERTIES = fst.kDeleteArcsProperties             # <<<<<<<<<<<<<<
  * STATE_SORT_PROPERTIES = fst.kStateSortProperties
  * ARC_SORT_PROPERTIES = fst.kArcSortProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kDeleteArcsProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2860, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kDeleteArcsProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2878, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_DELETE_ARC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2860, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_DELETE_ARC_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2878, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2861
+  /* "pywrapfst.pyx":2879
  * DELETE_STATE_PROPERTIES = fst.kDeleteStatesProperties
  * DELETE_ARC_PROPERTIES = fst.kDeleteArcsProperties
  * STATE_SORT_PROPERTIES = fst.kStateSortProperties             # <<<<<<<<<<<<<<
  * ARC_SORT_PROPERTIES = fst.kArcSortProperties
  * I_LABEL_INVARIANT_PROPERTIES = fst.kILabelInvariantProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kStateSortProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2861, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kStateSortProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2879, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_STATE_SORT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2861, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_STATE_SORT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2879, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2862
+  /* "pywrapfst.pyx":2880
  * DELETE_ARC_PROPERTIES = fst.kDeleteArcsProperties
  * STATE_SORT_PROPERTIES = fst.kStateSortProperties
  * ARC_SORT_PROPERTIES = fst.kArcSortProperties             # <<<<<<<<<<<<<<
  * I_LABEL_INVARIANT_PROPERTIES = fst.kILabelInvariantProperties
  * O_LABEL_INVARIANT_PROPERTIES = fst.kOLabelInvariantProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kArcSortProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2862, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kArcSortProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2880, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_SORT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2862, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_SORT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2880, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2863
+  /* "pywrapfst.pyx":2881
  * STATE_SORT_PROPERTIES = fst.kStateSortProperties
  * ARC_SORT_PROPERTIES = fst.kArcSortProperties
  * I_LABEL_INVARIANT_PROPERTIES = fst.kILabelInvariantProperties             # <<<<<<<<<<<<<<
  * O_LABEL_INVARIANT_PROPERTIES = fst.kOLabelInvariantProperties
  * WEIGHT_INVARIANT_PROPERTIES = fst.kWeightInvariantProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kILabelInvariantProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2863, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kILabelInvariantProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2881, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_I_LABEL_INVARIANT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2863, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_I_LABEL_INVARIANT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2881, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2864
+  /* "pywrapfst.pyx":2882
  * ARC_SORT_PROPERTIES = fst.kArcSortProperties
  * I_LABEL_INVARIANT_PROPERTIES = fst.kILabelInvariantProperties
  * O_LABEL_INVARIANT_PROPERTIES = fst.kOLabelInvariantProperties             # <<<<<<<<<<<<<<
  * WEIGHT_INVARIANT_PROPERTIES = fst.kWeightInvariantProperties
  * ADD_SUPERFINAL_PROPERTIES = fst.kAddSuperFinalProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kOLabelInvariantProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2864, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kOLabelInvariantProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2882, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_O_LABEL_INVARIANT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2864, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_O_LABEL_INVARIANT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2882, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2865
+  /* "pywrapfst.pyx":2883
  * I_LABEL_INVARIANT_PROPERTIES = fst.kILabelInvariantProperties
  * O_LABEL_INVARIANT_PROPERTIES = fst.kOLabelInvariantProperties
  * WEIGHT_INVARIANT_PROPERTIES = fst.kWeightInvariantProperties             # <<<<<<<<<<<<<<
  * ADD_SUPERFINAL_PROPERTIES = fst.kAddSuperFinalProperties
  * RM_SUPERFINAL_PROPERTIES = fst.kRmSuperFinalProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kWeightInvariantProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2865, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kWeightInvariantProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2883, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_WEIGHT_INVARIANT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2865, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_WEIGHT_INVARIANT_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2883, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2866
+  /* "pywrapfst.pyx":2884
  * O_LABEL_INVARIANT_PROPERTIES = fst.kOLabelInvariantProperties
  * WEIGHT_INVARIANT_PROPERTIES = fst.kWeightInvariantProperties
  * ADD_SUPERFINAL_PROPERTIES = fst.kAddSuperFinalProperties             # <<<<<<<<<<<<<<
  * RM_SUPERFINAL_PROPERTIES = fst.kRmSuperFinalProperties
  * BINARY_PROPERTIES = fst.kBinaryProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAddSuperFinalProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2866, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kAddSuperFinalProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2884, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ADD_SUPERFINAL_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2866, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ADD_SUPERFINAL_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2884, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2867
+  /* "pywrapfst.pyx":2885
  * WEIGHT_INVARIANT_PROPERTIES = fst.kWeightInvariantProperties
  * ADD_SUPERFINAL_PROPERTIES = fst.kAddSuperFinalProperties
  * RM_SUPERFINAL_PROPERTIES = fst.kRmSuperFinalProperties             # <<<<<<<<<<<<<<
  * BINARY_PROPERTIES = fst.kBinaryProperties
  * TRINARY_PROPERTIES = fst.kTrinaryProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kRmSuperFinalProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2867, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kRmSuperFinalProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2885, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_RM_SUPERFINAL_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2867, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_RM_SUPERFINAL_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2885, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2868
+  /* "pywrapfst.pyx":2886
  * ADD_SUPERFINAL_PROPERTIES = fst.kAddSuperFinalProperties
  * RM_SUPERFINAL_PROPERTIES = fst.kRmSuperFinalProperties
  * BINARY_PROPERTIES = fst.kBinaryProperties             # <<<<<<<<<<<<<<
  * TRINARY_PROPERTIES = fst.kTrinaryProperties
  * POS_TRINARY_PROPERTIES = fst.kPosTrinaryProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kBinaryProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2868, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kBinaryProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2886, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_BINARY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2868, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_BINARY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2886, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2869
+  /* "pywrapfst.pyx":2887
  * RM_SUPERFINAL_PROPERTIES = fst.kRmSuperFinalProperties
  * BINARY_PROPERTIES = fst.kBinaryProperties
  * TRINARY_PROPERTIES = fst.kTrinaryProperties             # <<<<<<<<<<<<<<
  * POS_TRINARY_PROPERTIES = fst.kPosTrinaryProperties
  * NEG_TRINARY_PROPERTIES = fst.kNegTrinaryProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kTrinaryProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2869, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kTrinaryProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2887, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_TRINARY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2869, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_TRINARY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2887, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2870
+  /* "pywrapfst.pyx":2888
  * BINARY_PROPERTIES = fst.kBinaryProperties
  * TRINARY_PROPERTIES = fst.kTrinaryProperties
  * POS_TRINARY_PROPERTIES = fst.kPosTrinaryProperties             # <<<<<<<<<<<<<<
  * NEG_TRINARY_PROPERTIES = fst.kNegTrinaryProperties
  * FST_PROPERTIES = fst.kFstProperties
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kPosTrinaryProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2870, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kPosTrinaryProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2888, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_POS_TRINARY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2870, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_POS_TRINARY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2888, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2871
+  /* "pywrapfst.pyx":2889
  * TRINARY_PROPERTIES = fst.kTrinaryProperties
  * POS_TRINARY_PROPERTIES = fst.kPosTrinaryProperties
  * NEG_TRINARY_PROPERTIES = fst.kNegTrinaryProperties             # <<<<<<<<<<<<<<
  * FST_PROPERTIES = fst.kFstProperties
  * 
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNegTrinaryProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2871, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kNegTrinaryProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2889, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NEG_TRINARY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2871, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NEG_TRINARY_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2889, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2872
+  /* "pywrapfst.pyx":2890
  * POS_TRINARY_PROPERTIES = fst.kPosTrinaryProperties
  * NEG_TRINARY_PROPERTIES = fst.kNegTrinaryProperties
  * FST_PROPERTIES = fst.kFstProperties             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kFstProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2872, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(fst::kFstProperties); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2890, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FST_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2872, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_FST_PROPERTIES, __pyx_t_1) < 0) __PYX_ERR(0, 2890, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2878
+  /* "pywrapfst.pyx":2896
  * 
  * 
  * ARC_I_LABEL_VALUE = fst.kArcILabelValue             # <<<<<<<<<<<<<<
  * ARC_O_LABEL_VALUE = fst.kArcOLabelValue
  * ARC_WEIGHT_VALUE = fst.kArcWeightValue
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcILabelValue); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2878, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcILabelValue); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2896, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_I_LABEL_VALUE, __pyx_t_1) < 0) __PYX_ERR(0, 2878, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_I_LABEL_VALUE, __pyx_t_1) < 0) __PYX_ERR(0, 2896, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2879
+  /* "pywrapfst.pyx":2897
  * 
  * ARC_I_LABEL_VALUE = fst.kArcILabelValue
  * ARC_O_LABEL_VALUE = fst.kArcOLabelValue             # <<<<<<<<<<<<<<
  * ARC_WEIGHT_VALUE = fst.kArcWeightValue
  * ARC_NEXT_STATE_VALUE = fst.kArcNextStateValue
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcOLabelValue); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2879, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcOLabelValue); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2897, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_O_LABEL_VALUE, __pyx_t_1) < 0) __PYX_ERR(0, 2879, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_O_LABEL_VALUE, __pyx_t_1) < 0) __PYX_ERR(0, 2897, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2880
+  /* "pywrapfst.pyx":2898
  * ARC_I_LABEL_VALUE = fst.kArcILabelValue
  * ARC_O_LABEL_VALUE = fst.kArcOLabelValue
  * ARC_WEIGHT_VALUE = fst.kArcWeightValue             # <<<<<<<<<<<<<<
  * ARC_NEXT_STATE_VALUE = fst.kArcNextStateValue
  * ARC_NO_CACHE = fst.kArcNoCache
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcWeightValue); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2880, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcWeightValue); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2898, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_WEIGHT_VALUE, __pyx_t_1) < 0) __PYX_ERR(0, 2880, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_WEIGHT_VALUE, __pyx_t_1) < 0) __PYX_ERR(0, 2898, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2881
+  /* "pywrapfst.pyx":2899
  * ARC_O_LABEL_VALUE = fst.kArcOLabelValue
  * ARC_WEIGHT_VALUE = fst.kArcWeightValue
  * ARC_NEXT_STATE_VALUE = fst.kArcNextStateValue             # <<<<<<<<<<<<<<
  * ARC_NO_CACHE = fst.kArcNoCache
  * ARC_VALUE_FLAGS = fst.kArcValueFlags
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcNextStateValue); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2881, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcNextStateValue); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2899, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_NEXT_STATE_VALUE, __pyx_t_1) < 0) __PYX_ERR(0, 2881, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_NEXT_STATE_VALUE, __pyx_t_1) < 0) __PYX_ERR(0, 2899, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2882
+  /* "pywrapfst.pyx":2900
  * ARC_WEIGHT_VALUE = fst.kArcWeightValue
  * ARC_NEXT_STATE_VALUE = fst.kArcNextStateValue
  * ARC_NO_CACHE = fst.kArcNoCache             # <<<<<<<<<<<<<<
  * ARC_VALUE_FLAGS = fst.kArcValueFlags
  * ARC_FLAGS = fst.kArcFlags
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcNoCache); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2882, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcNoCache); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2900, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_NO_CACHE, __pyx_t_1) < 0) __PYX_ERR(0, 2882, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_NO_CACHE, __pyx_t_1) < 0) __PYX_ERR(0, 2900, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2883
+  /* "pywrapfst.pyx":2901
  * ARC_NEXT_STATE_VALUE = fst.kArcNextStateValue
  * ARC_NO_CACHE = fst.kArcNoCache
  * ARC_VALUE_FLAGS = fst.kArcValueFlags             # <<<<<<<<<<<<<<
  * ARC_FLAGS = fst.kArcFlags
  * 
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcValueFlags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2883, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcValueFlags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2901, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_VALUE_FLAGS, __pyx_t_1) < 0) __PYX_ERR(0, 2883, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_VALUE_FLAGS, __pyx_t_1) < 0) __PYX_ERR(0, 2901, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2884
+  /* "pywrapfst.pyx":2902
  * ARC_NO_CACHE = fst.kArcNoCache
  * ARC_VALUE_FLAGS = fst.kArcValueFlags
  * ARC_FLAGS = fst.kArcFlags             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcFlags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2884, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kArcFlags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2902, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_FLAGS, __pyx_t_1) < 0) __PYX_ERR(0, 2884, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ARC_FLAGS, __pyx_t_1) < 0) __PYX_ERR(0, 2902, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2890
+  /* "pywrapfst.pyx":2908
  * 
  * 
  * ENCODE_LABELS = fst.kEncodeLabels             # <<<<<<<<<<<<<<
  * ENCODE_WEIGHTS = fst.kEncodeWeights
  * ENCODE_FLAGS = fst.kEncodeFlags
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kEncodeLabels); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2890, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kEncodeLabels); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2908, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ENCODE_LABELS, __pyx_t_1) < 0) __PYX_ERR(0, 2890, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ENCODE_LABELS, __pyx_t_1) < 0) __PYX_ERR(0, 2908, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2891
+  /* "pywrapfst.pyx":2909
  * 
  * ENCODE_LABELS = fst.kEncodeLabels
  * ENCODE_WEIGHTS = fst.kEncodeWeights             # <<<<<<<<<<<<<<
  * ENCODE_FLAGS = fst.kEncodeFlags
  * 
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kEncodeWeights); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2891, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kEncodeWeights); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2909, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ENCODE_WEIGHTS, __pyx_t_1) < 0) __PYX_ERR(0, 2891, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ENCODE_WEIGHTS, __pyx_t_1) < 0) __PYX_ERR(0, 2909, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":2892
+  /* "pywrapfst.pyx":2910
  * ENCODE_LABELS = fst.kEncodeLabels
  * ENCODE_WEIGHTS = fst.kEncodeWeights
  * ENCODE_FLAGS = fst.kEncodeFlags             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kEncodeFlags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2892, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint32_t(fst::kEncodeFlags); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2910, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ENCODE_FLAGS, __pyx_t_1) < 0) __PYX_ERR(0, 2892, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ENCODE_FLAGS, __pyx_t_1) < 0) __PYX_ERR(0, 2910, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":3258
+  /* "pywrapfst.pyx":3276
  * 
  * cdef _Fst _map(_Fst ifst,
  *                float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                map_type=b"identity",
  *                double power=1.,
  */
-  __pyx_k__67 = fst::kDelta;
+  __pyx_k__31 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3272
+  /* "pywrapfst.pyx":3290
  * 
  * cpdef _Fst arcmap(_Fst ifst,
  *                   float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                   map_type=b"identity",
  *                   double power=1.,
  */
-  __pyx_k__68 = fst::kDelta;
+  __pyx_k__32 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3271
+  /* "pywrapfst.pyx":3289
  * 
  * 
  * cpdef _Fst arcmap(_Fst ifst,             # <<<<<<<<<<<<<<
  *                   float delta=fst.kDelta,
  *                   map_type=b"identity",
  */
-  __pyx_k__68 = fst::kDelta;
+  __pyx_k__32 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3384
+  /* "pywrapfst.pyx":3402
  * 
  * cpdef _MutableFst determinize(_Fst ifst,
  *                               float delta=fst.kShortestDelta,             # <<<<<<<<<<<<<<
  *                               det_type=b"functional",
  *                               int64 nstate=fst.kNoStateId,
  */
-  __pyx_k__69 = fst::kShortestDelta;
+  __pyx_k__33 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":3386
+  /* "pywrapfst.pyx":3404
  *                               float delta=fst.kShortestDelta,
  *                               det_type=b"functional",
  *                               int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                               int64 subsequential_label=0,
  *                               weight=None,
  */
-  __pyx_k__70 = fst::kNoStateId;
+  __pyx_k__34 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":3384
+  /* "pywrapfst.pyx":3402
  * 
  * cpdef _MutableFst determinize(_Fst ifst,
  *                               float delta=fst.kShortestDelta,             # <<<<<<<<<<<<<<
  *                               det_type=b"functional",
  *                               int64 nstate=fst.kNoStateId,
  */
-  __pyx_k__69 = fst::kShortestDelta;
+  __pyx_k__33 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":3386
+  /* "pywrapfst.pyx":3404
  *                               float delta=fst.kShortestDelta,
  *                               det_type=b"functional",
  *                               int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                               int64 subsequential_label=0,
  *                               weight=None,
  */
-  __pyx_k__70 = fst::kNoStateId;
+  __pyx_k__34 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":3477
+  /* "pywrapfst.pyx":3495
  * 
  * cpdef _MutableFst disambiguate(_Fst ifst,
  *                                float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                                int64 nstate=fst.kNoStateId,
  *                                int64 subsequential_label=0,
  */
-  __pyx_k__71 = fst::kDelta;
+  __pyx_k__35 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3478
+  /* "pywrapfst.pyx":3496
  * cpdef _MutableFst disambiguate(_Fst ifst,
  *                                float delta=fst.kDelta,
  *                                int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                                int64 subsequential_label=0,
  *                                weight=None):
  */
-  __pyx_k__72 = fst::kNoStateId;
+  __pyx_k__36 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":3477
+  /* "pywrapfst.pyx":3495
  * 
  * cpdef _MutableFst disambiguate(_Fst ifst,
  *                                float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                                int64 nstate=fst.kNoStateId,
  *                                int64 subsequential_label=0,
  */
-  __pyx_k__71 = fst::kDelta;
+  __pyx_k__35 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3478
+  /* "pywrapfst.pyx":3496
  * cpdef _MutableFst disambiguate(_Fst ifst,
  *                                float delta=fst.kDelta,
  *                                int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                                int64 subsequential_label=0,
  *                                weight=None):
  */
-  __pyx_k__72 = fst::kNoStateId;
+  __pyx_k__36 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":3548
+  /* "pywrapfst.pyx":3566
  * 
  * 
  * cpdef bool equal(_Fst ifst1, _Fst ifst2, float delta=fst.kDelta):             # <<<<<<<<<<<<<<
  *   """
  *   equal(ifst1, ifst2, delta=0.0009765625)
  */
-  __pyx_k__73 = fst::kDelta;
-  __pyx_k__73 = fst::kDelta;
+  __pyx_k__37 = fst::kDelta;
+  __pyx_k__37 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3571
+  /* "pywrapfst.pyx":3589
  * 
  * 
  * cpdef bool equivalent(_Fst ifst1, _Fst ifst2, float delta=fst.kDelta) except *:             # <<<<<<<<<<<<<<
  *   """
  *   equivalent(ifst1, ifst2, delta=0.0009765625)
  */
-  __pyx_k__74 = fst::kDelta;
-  __pyx_k__74 = fst::kDelta;
+  __pyx_k__38 = fst::kDelta;
+  __pyx_k__38 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3627
+  /* "pywrapfst.pyx":3645
  * 
  * 
  * cpdef bool isomorphic(_Fst ifst1, _Fst ifst2, float delta=fst.kDelta):             # <<<<<<<<<<<<<<
  *   """
  *   isomorphic(ifst1, ifst2, delta=0.0009765625)
  */
-  __pyx_k__75 = fst::kDelta;
-  __pyx_k__75 = fst::kDelta;
+  __pyx_k__39 = fst::kDelta;
+  __pyx_k__39 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3654
+  /* "pywrapfst.pyx":3672
  * 
  * cpdef _MutableFst prune(_Fst ifst,
  *                         float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                         int64 nstate=fst.kNoStateId,
  *                         weight=None):
  */
-  __pyx_k__76 = fst::kDelta;
+  __pyx_k__40 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3655
+  /* "pywrapfst.pyx":3673
  * cpdef _MutableFst prune(_Fst ifst,
  *                         float delta=fst.kDelta,
  *                         int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                         weight=None):
  *   """
  */
-  __pyx_k__77 = fst::kNoStateId;
+  __pyx_k__41 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":3654
+  /* "pywrapfst.pyx":3672
  * 
  * cpdef _MutableFst prune(_Fst ifst,
  *                         float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                         int64 nstate=fst.kNoStateId,
  *                         weight=None):
  */
-  __pyx_k__76 = fst::kDelta;
+  __pyx_k__40 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3655
+  /* "pywrapfst.pyx":3673
  * cpdef _MutableFst prune(_Fst ifst,
  *                         float delta=fst.kDelta,
  *                         int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                         weight=None):
  *   """
  */
-  __pyx_k__77 = fst::kNoStateId;
+  __pyx_k__41 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":3687
+  /* "pywrapfst.pyx":3705
  * 
  * cpdef _MutableFst push(_Fst ifst,
  *                        float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                        bool push_weights=False,
  *                        bool push_labels=False,
  */
-  __pyx_k__78 = fst::kDelta;
+  __pyx_k__42 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3686
+  /* "pywrapfst.pyx":3704
  * 
  * 
  * cpdef _MutableFst push(_Fst ifst,             # <<<<<<<<<<<<<<
  *                        float delta=fst.kDelta,
  *                        bool push_weights=False,
  */
-  __pyx_k__78 = fst::kDelta;
+  __pyx_k__42 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3743
+  /* "pywrapfst.pyx":3761
  *                           _Fst ifst2,
  *                           int32 npath=1,
  *                           float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                           time_t seed=0,
  *                           select=b"uniform",
  */
-  __pyx_k__79 = fst::kDelta;
+  __pyx_k__43 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3746
+  /* "pywrapfst.pyx":3764
  *                           time_t seed=0,
  *                           select=b"uniform",
  *                           int32 max_length=INT32_MAX) except *:             # <<<<<<<<<<<<<<
  *   """
  *   randequivalent(ifst1, ifst2, npath=1, delta=0.0009765625, seed=0,
  */
-  __pyx_k__80 = INT32_MAX;
+  __pyx_k__44 = INT32_MAX;
 
-  /* "pywrapfst.pyx":3743
+  /* "pywrapfst.pyx":3761
  *                           _Fst ifst2,
  *                           int32 npath=1,
  *                           float delta=fst.kDelta,             # <<<<<<<<<<<<<<
  *                           time_t seed=0,
  *                           select=b"uniform",
  */
-  __pyx_k__79 = fst::kDelta;
+  __pyx_k__43 = fst::kDelta;
 
-  /* "pywrapfst.pyx":3746
+  /* "pywrapfst.pyx":3764
  *                           time_t seed=0,
  *                           select=b"uniform",
  *                           int32 max_length=INT32_MAX) except *:             # <<<<<<<<<<<<<<
  *   """
  *   randequivalent(ifst1, ifst2, npath=1, delta=0.0009765625, seed=0,
  */
-  __pyx_k__80 = INT32_MAX;
+  __pyx_k__44 = INT32_MAX;
 
-  /* "pywrapfst.pyx":3790
+  /* "pywrapfst.pyx":3808
  *                           time_t seed=0,
  *                           select=b"uniform",
  *                           int32 max_length=INT32_MAX,             # <<<<<<<<<<<<<<
  *                           bool weighted=False,
  *                           bool remove_total_weight=False):
  */
-  __pyx_k__81 = INT32_MAX;
+  __pyx_k__45 = INT32_MAX;
 
-  /* "pywrapfst.pyx":3786
+  /* "pywrapfst.pyx":3804
  * 
  * 
  * cpdef _MutableFst randgen(_Fst ifst,             # <<<<<<<<<<<<<<
  *                           int32 npath=1,
  *                           time_t seed=0,
  */
-  __pyx_k__81 = INT32_MAX;
+  __pyx_k__45 = INT32_MAX;
 
-  /* "pywrapfst.pyx":3928
+  /* "pywrapfst.pyx":3946
  * 
  * cdef vector[fst.WeightClass] *_shortestdistance(_Fst ifst,
  *                                                 float delta=fst.kShortestDelta,             # <<<<<<<<<<<<<<
  *                                                 int64 nstate=fst.kNoStateId,
  *                                                 queue_type=b"auto",
  */
-  __pyx_k__82 = fst::kShortestDelta;
+  __pyx_k__46 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":3929
+  /* "pywrapfst.pyx":3947
  * cdef vector[fst.WeightClass] *_shortestdistance(_Fst ifst,
  *                                                 float delta=fst.kShortestDelta,
  *                                                 int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                                                 queue_type=b"auto",
  *                                                 bool reverse=False) except *:
  */
-  __pyx_k__83 = fst::kNoStateId;
+  __pyx_k__47 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":3950
+  /* "pywrapfst.pyx":3968
  * 
  * def shortestdistance(_Fst ifst,
  *                      float delta=fst.kShortestDelta,             # <<<<<<<<<<<<<<
  *                      int64 nstate=fst.kNoStateId,
  *                      queue_type=b"auto",
  */
-  __pyx_k__84 = fst::kShortestDelta;
+  __pyx_k__48 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":3951
+  /* "pywrapfst.pyx":3969
  * def shortestdistance(_Fst ifst,
  *                      float delta=fst.kShortestDelta,
  *                      int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                      queue_type=b"auto",
  *                      bool reverse=False):
  */
-  __pyx_k__85 = fst::kNoStateId;
+  __pyx_k__49 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":3949
+  /* "pywrapfst.pyx":3967
  * 
  * 
  * def shortestdistance(_Fst ifst,             # <<<<<<<<<<<<<<
  *                      float delta=fst.kShortestDelta,
  *                      int64 nstate=fst.kNoStateId,
  */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_51shortestdistance, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3949, __pyx_L1_error)
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_53shortestdistance, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3967, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_shortestdistance, __pyx_t_1) < 0) __PYX_ERR(0, 3949, __pyx_L1_error)
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_shortestdistance, __pyx_t_1) < 0) __PYX_ERR(0, 3967, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "pywrapfst.pyx":3987
+  /* "pywrapfst.pyx":4005
  * 
  * cpdef _MutableFst shortestpath(_Fst ifst,
  *                                float delta=fst.kShortestDelta,             # <<<<<<<<<<<<<<
  *                                int32 nshortest=1,
  *                                int64 nstate=fst.kNoStateId,
  */
-  __pyx_k__86 = fst::kShortestDelta;
+  __pyx_k__50 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":3989
+  /* "pywrapfst.pyx":4007
  *                                float delta=fst.kShortestDelta,
  *                                int32 nshortest=1,
  *                                int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                                queue_type=b"auto",
  *                                bool unique=False,
  */
-  __pyx_k__87 = fst::kNoStateId;
+  __pyx_k__51 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":3987
+  /* "pywrapfst.pyx":4005
  * 
  * cpdef _MutableFst shortestpath(_Fst ifst,
  *                                float delta=fst.kShortestDelta,             # <<<<<<<<<<<<<<
  *                                int32 nshortest=1,
  *                                int64 nstate=fst.kNoStateId,
  */
-  __pyx_k__86 = fst::kShortestDelta;
+  __pyx_k__50 = fst::kShortestDelta;
 
-  /* "pywrapfst.pyx":3989
+  /* "pywrapfst.pyx":4007
  *                                float delta=fst.kShortestDelta,
  *                                int32 nshortest=1,
  *                                int64 nstate=fst.kNoStateId,             # <<<<<<<<<<<<<<
  *                                queue_type=b"auto",
  *                                bool unique=False,
  */
-  __pyx_k__87 = fst::kNoStateId;
+  __pyx_k__51 = fst::kNoStateId;
 
-  /* "pywrapfst.pyx":4140
+  /* "pywrapfst.pyx":4158
  * 
  *   def __cinit__(self,
  *                 string fst_type=b"vector",             # <<<<<<<<<<<<<<
  *                 string arc_type=b"standard",
  *                 SymbolTable isymbols=None,
  */
-  __pyx_t_6 = __pyx_convert_string_from_py_std__in_string(__pyx_n_b_vector); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4140, __pyx_L1_error)
-  __pyx_k__88 = __pyx_t_6;
+  __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_n_b_vector); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4158, __pyx_L1_error)
+  __pyx_k__52 = __pyx_t_5;
 
-  /* "pywrapfst.pyx":4141
+  /* "pywrapfst.pyx":4159
  *   def __cinit__(self,
  *                 string fst_type=b"vector",
  *                 string arc_type=b"standard",             # <<<<<<<<<<<<<<
  *                 SymbolTable isymbols=None,
  *                 SymbolTable osymbols=None,
  */
-  __pyx_t_6 = __pyx_convert_string_from_py_std__in_string(__pyx_n_b_standard); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4141, __pyx_L1_error)
-  __pyx_k__89 = __pyx_t_6;
+  __pyx_t_5 = __pyx_convert_string_from_py_std__in_string(__pyx_n_b_standard); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4159, __pyx_L1_error)
+  __pyx_k__53 = __pyx_t_5;
 
-  /* "pywrapfst.pyx":4239
+  /* "pywrapfst.pyx":4260
  * 
  *   @classmethod
  *   def open(cls, *filenames):             # <<<<<<<<<<<<<<
  *     """
  *     FarReader.open(*filenames)
  */
-  __pyx_t_1 = __Pyx_GetNameInClass((PyObject *)__pyx_ptype_9pywrapfst_FarReader, __pyx_n_s_open); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4239, __pyx_L1_error)
+  __Pyx_GetNameInClass(__pyx_t_1, (PyObject *)__pyx_ptype_9pywrapfst_FarReader, __pyx_n_s_open); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4260, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
 
-  /* "pywrapfst.pyx":4238
+  /* "pywrapfst.pyx":4259
  *     return "<{} FarReader at 0x{:x}>".format(self.far_type(), id(self))
  * 
  *   @classmethod             # <<<<<<<<<<<<<<
  *   def open(cls, *filenames):
  *     """
  */
-  __pyx_t_2 = __Pyx_Method_ClassMethod(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4238, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_Method_ClassMethod(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4259, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_FarReader->tp_dict, __pyx_n_s_open, __pyx_t_2) < 0) __PYX_ERR(0, 4239, __pyx_L1_error)
+  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_FarReader->tp_dict, __pyx_n_s_open, __pyx_t_2) < 0) __PYX_ERR(0, 4260, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   PyType_Modified(__pyx_ptype_9pywrapfst_FarReader);
 
-  /* "pywrapfst.pyx":4389
+  /* "pywrapfst.pyx":4411
  * 
  *   @classmethod
  *   def create(cls, filename, arc_type=b"standard", far_type=b"default"):             # <<<<<<<<<<<<<<
  *     """
  *     FarWriter.
  */
-  __pyx_t_2 = __Pyx_GetNameInClass((PyObject *)__pyx_ptype_9pywrapfst_FarWriter, __pyx_n_s_create); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4389, __pyx_L1_error)
+  __Pyx_GetNameInClass(__pyx_t_2, (PyObject *)__pyx_ptype_9pywrapfst_FarWriter, __pyx_n_s_create); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4411, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
 
-  /* "pywrapfst.pyx":4388
+  /* "pywrapfst.pyx":4410
  *     return "<{} FarWriter at 0x{:x}>".format(self.far_type(), id(self))
  * 
  *   @classmethod             # <<<<<<<<<<<<<<
  *   def create(cls, filename, arc_type=b"standard", far_type=b"default"):
  *     """
  */
-  __pyx_t_1 = __Pyx_Method_ClassMethod(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4388, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_Method_ClassMethod(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4410, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_FarWriter->tp_dict, __pyx_n_s_create, __pyx_t_1) < 0) __PYX_ERR(0, 4389, __pyx_L1_error)
+  if (PyDict_SetItem((PyObject *)__pyx_ptype_9pywrapfst_FarWriter->tp_dict, __pyx_n_s_create, __pyx_t_1) < 0) __PYX_ERR(0, 4411, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   PyType_Modified(__pyx_ptype_9pywrapfst_FarWriter);
 
-  /* "pywrapfst.pyx":4488
- * 
+  /* "pywrapfst.pyx":4503
  * 
- * _fst_error_fatal_old = fst.FLAGS_fst_error_fatal             # <<<<<<<<<<<<<<
- * fst.FLAGS_fst_error_fatal = False
- * 
- */
-  __pyx_t_1 = __Pyx_PyBool_FromLong(FLAGS_fst_error_fatal); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4488, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_fst_error_fatal_old, __pyx_t_1) < 0) __PYX_ERR(0, 4488, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-  /* "pywrapfst.pyx":4489
- * 
- * _fst_error_fatal_old = fst.FLAGS_fst_error_fatal
+ * # Masks fst_error_fatal in-module.
  * fst.FLAGS_fst_error_fatal = False             # <<<<<<<<<<<<<<
  * 
- * 
  */
   FLAGS_fst_error_fatal = 0;
 
-  /* "pywrapfst.pyx":4492
- * 
- * 
- * @atexit.register             # <<<<<<<<<<<<<<
- * def _reset_fst_error_fatal():
- *   fst.FLAGS_fst_error_fatal = _fst_error_fatal_old
- */
-  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_atexit); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4492, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_register); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4492, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-  /* "pywrapfst.pyx":4493
- * 
- * @atexit.register
- * def _reset_fst_error_fatal():             # <<<<<<<<<<<<<<
- *   fst.FLAGS_fst_error_fatal = _fst_error_fatal_old
- * 
- */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_9pywrapfst_59_reset_fst_error_fatal, NULL, __pyx_n_s_pywrapfst_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4493, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-
-  /* "pywrapfst.pyx":4492
- * 
- * 
- * @atexit.register             # <<<<<<<<<<<<<<
- * def _reset_fst_error_fatal():
- *   fst.FLAGS_fst_error_fatal = _fst_error_fatal_old
- */
-  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4492, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_reset_fst_error_fatal, __pyx_t_3) < 0) __PYX_ERR(0, 4493, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
   /* "pywrapfst.pyx":1
- * #cython: nonecheck=True             # <<<<<<<<<<<<<<
+ * #cython: nonecheck=True, c_string_type=unicode, c_string_encoding=utf8             # <<<<<<<<<<<<<<
  * # Licensed under the Apache License, Version 2.0 (the "License");
  * # you may not use this file except in compliance with the License.
  */
-  __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test_2, __pyx_t_3) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test_2, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
   /* "vector.from_py":45
  * 
- * @cname("__pyx_convert_vector_from_py_std_3a__3a_string")
- * cdef vector[X] __pyx_convert_vector_from_py_std_3a__3a_string(object o) except *:             # <<<<<<<<<<<<<<
+ * @cname("__pyx_convert_vector_from_py___pyx_t_10basictypes_int64")
+ * cdef vector[X] __pyx_convert_vector_from_py___pyx_t_10basictypes_int64(object o) except *:             # <<<<<<<<<<<<<<
  *     cdef vector[X] v
  *     for item in o:
  */
@@ -53093,9 +51472,9 @@ if (!__Pyx_RefNanny) {
   __Pyx_XDECREF(__pyx_t_4);
   if (__pyx_m) {
     if (__pyx_d) {
-      __Pyx_AddTraceback("init pywrapfst", 0, __pyx_lineno, __pyx_filename);
+      __Pyx_AddTraceback("init pywrapfst", __pyx_clineno, __pyx_lineno, __pyx_filename);
     }
-    Py_DECREF(__pyx_m); __pyx_m = 0;
+    Py_CLEAR(__pyx_m);
   } else if (!PyErr_Occurred()) {
     PyErr_SetString(PyExc_ImportError, "init pywrapfst");
   }
@@ -53116,9 +51495,9 @@ if (!__Pyx_RefNanny) {
 static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
     PyObject *m = NULL, *p = NULL;
     void *r = NULL;
-    m = PyImport_ImportModule((char *)modname);
+    m = PyImport_ImportModule(modname);
     if (!m) goto end;
-    p = PyObject_GetAttrString(m, (char *)"RefNannyAPI");
+    p = PyObject_GetAttrString(m, "RefNannyAPI");
     if (!p) goto end;
     r = PyLong_AsVoidPtr(p);
 end:
@@ -53164,7 +51543,7 @@ static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, P
     PyObject *self = PyCFunction_GET_SELF(func);
     int flags = PyCFunction_GET_FLAGS(func);
     assert(PyCFunction_Check(func));
-    assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS)));
+    assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS)));
     assert(nargs >= 0);
     assert(nargs == 0 || args != NULL);
     /* _PyCFunction_FastCallDict() must not be called with an exception set,
@@ -53172,16 +51551,15 @@ static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, P
        caller loses its exception */
     assert(!PyErr_Occurred());
     if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) {
-        return (*((__Pyx_PyCFunctionFastWithKeywords)meth)) (self, args, nargs, NULL);
+        return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL);
     } else {
-        return (*((__Pyx_PyCFunctionFast)meth)) (self, args, nargs);
+        return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs);
     }
 }
 #endif
 
 /* PyFunctionFastCall */
 #if CYTHON_FAST_PYCALL
-#include "frameobject.h"
 static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na,
                                                PyObject *globals) {
     PyFrameObject *f;
@@ -53199,7 +51577,7 @@ static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args
     if (f == NULL) {
         return NULL;
     }
-    fastlocals = f->f_localsplus;
+    fastlocals = __Pyx_PyFrame_GetLocalsplus(f);
     for (i = 0; i < na; i++) {
         Py_INCREF(*args);
         fastlocals[i] = *args++;
@@ -53319,6 +51697,35 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg
 }
 #endif
 
+/* PyObjectCall2Args */
+static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) {
+    PyObject *args, *result = NULL;
+    #if CYTHON_FAST_PYCALL
+    if (PyFunction_Check(function)) {
+        PyObject *args[2] = {arg1, arg2};
+        return __Pyx_PyFunction_FastCall(function, args, 2);
+    }
+    #endif
+    #if CYTHON_FAST_PYCCALL
+    if (__Pyx_PyFastCFunction_Check(function)) {
+        PyObject *args[2] = {arg1, arg2};
+        return __Pyx_PyCFunction_FastCall(function, args, 2);
+    }
+    #endif
+    args = PyTuple_New(2);
+    if (unlikely(!args)) goto done;
+    Py_INCREF(arg1);
+    PyTuple_SET_ITEM(args, 0, arg1);
+    Py_INCREF(arg2);
+    PyTuple_SET_ITEM(args, 1, arg2);
+    Py_INCREF(function);
+    result = __Pyx_PyObject_Call(function, args, NULL);
+    Py_DECREF(args);
+    Py_DECREF(function);
+done:
+    return result;
+}
+
 /* PyObjectCallMethO */
 #if CYTHON_COMPILING_IN_CPYTHON
 static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) {
@@ -53380,34 +51787,42 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObjec
 #endif
 
 /* GetModuleGlobalName */
-static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) {
+#if CYTHON_USE_DICT_VERSIONS
+static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value)
+#else
+static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name)
+#endif
+{
     PyObject *result;
 #if !CYTHON_AVOID_BORROWED_REFS
 #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1
     result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash);
+    __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version)
     if (likely(result)) {
-        Py_INCREF(result);
+        return __Pyx_NewRef(result);
     } else if (unlikely(PyErr_Occurred())) {
-        result = NULL;
-    } else {
+        return NULL;
+    }
 #else
     result = PyDict_GetItem(__pyx_d, name);
+    __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version)
     if (likely(result)) {
-        Py_INCREF(result);
-    } else {
+        return __Pyx_NewRef(result);
+    }
 #endif
 #else
     result = PyObject_GetItem(__pyx_d, name);
-    if (!result) {
-        PyErr_Clear();
-#endif
-        result = __Pyx_GetBuiltinName(name);
+    __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version)
+    if (likely(result)) {
+        return __Pyx_NewRef(result);
     }
-    return result;
+    PyErr_Clear();
+#endif
+    return __Pyx_GetBuiltinName(name);
 }
 
 /* PyErrFetchRestore */
-    #if CYTHON_FAST_THREAD_STATE
+#if CYTHON_FAST_THREAD_STATE
 static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) {
     PyObject *tmp_type, *tmp_value, *tmp_tb;
     tmp_type = tstate->curexc_type;
@@ -53431,7 +51846,7 @@ static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject
 #endif
 
 /* RaiseException */
-    #if PY_MAJOR_VERSION < 3
+#if PY_MAJOR_VERSION < 3
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
                         CYTHON_UNUSED PyObject *cause) {
     __Pyx_PyThreadState_declare
@@ -53590,7 +52005,7 @@ bad:
 #endif
 
 /* RaiseArgTupleInvalid */
-    static void __Pyx_RaiseArgtupleInvalid(
+static void __Pyx_RaiseArgtupleInvalid(
     const char* func_name,
     int exact,
     Py_ssize_t num_min,
@@ -53616,7 +52031,7 @@ bad:
 }
 
 /* RaiseDoubleKeywords */
-    static void __Pyx_RaiseDoubleKeywordsError(
+static void __Pyx_RaiseDoubleKeywordsError(
     const char* func_name,
     PyObject* kw_name)
 {
@@ -53630,7 +52045,7 @@ bad:
 }
 
 /* ParseKeywords */
-    static int __Pyx_ParseOptionalKeywords(
+static int __Pyx_ParseOptionalKeywords(
     PyObject *kwds,
     PyObject **argnames[],
     PyObject *kwds2,
@@ -53732,7 +52147,7 @@ bad:
 }
 
 /* PyObjectCallNoArg */
-    #if CYTHON_COMPILING_IN_CPYTHON
+#if CYTHON_COMPILING_IN_CPYTHON
 static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
 #if CYTHON_FAST_PYCALL
     if (PyFunction_Check(func)) {
@@ -53740,10 +52155,11 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
     }
 #endif
 #ifdef __Pyx_CyFunction_USED
-    if (likely(PyCFunction_Check(func) || __Pyx_TypeCheck(func, __pyx_CyFunctionType))) {
+    if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func)))
 #else
-    if (likely(PyCFunction_Check(func))) {
+    if (likely(PyCFunction_Check(func)))
 #endif
+    {
         if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) {
             return __Pyx_PyObject_CallMethO(func, NULL);
         }
@@ -53753,7 +52169,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
 #endif
 
 /* ExtTypeTest */
-      static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
     if (unlikely(!type)) {
         PyErr_SetString(PyExc_SystemError, "Missing type object");
         return 0;
@@ -53766,7 +52182,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
 }
 
 /* ArgTypeTest */
-      static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact)
+static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact)
 {
     if (unlikely(!type)) {
         PyErr_SetString(PyExc_SystemError, "Missing type object");
@@ -53787,7 +52203,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
 }
 
 /* WriteUnraisableException */
-      static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
+static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
                                   CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename,
                                   int full_traceback, CYTHON_UNUSED int nogil) {
     PyObject *old_exc, *old_val, *old_tb;
@@ -53829,7 +52245,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
 }
 
 /* KeywordStringCheck */
-      static int __Pyx_CheckKeywordStrings(
+static int __Pyx_CheckKeywordStrings(
     PyObject *kwdict,
     const char* function_name,
     int kw_allowed)
@@ -53868,13 +52284,29 @@ invalid_keyword:
     return 0;
 }
 
+/* GetTopmostException */
+#if CYTHON_USE_EXC_INFO_STACK
+static _PyErr_StackItem *
+__Pyx_PyErr_GetTopmostException(PyThreadState *tstate)
+{
+    _PyErr_StackItem *exc_info = tstate->exc_info;
+    while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) &&
+           exc_info->previous_item != NULL)
+    {
+        exc_info = exc_info->previous_item;
+    }
+    return exc_info;
+}
+#endif
+
 /* SaveResetException */
-      #if CYTHON_FAST_THREAD_STATE
+#if CYTHON_FAST_THREAD_STATE
 static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
-    #if PY_VERSION_HEX >= 0x030700A2
-    *type = tstate->exc_state.exc_type;
-    *value = tstate->exc_state.exc_value;
-    *tb = tstate->exc_state.exc_traceback;
+    #if CYTHON_USE_EXC_INFO_STACK
+    _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate);
+    *type = exc_info->exc_type;
+    *value = exc_info->exc_value;
+    *tb = exc_info->exc_traceback;
     #else
     *type = tstate->exc_type;
     *value = tstate->exc_value;
@@ -53886,13 +52318,14 @@ static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject *
 }
 static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) {
     PyObject *tmp_type, *tmp_value, *tmp_tb;
-    #if PY_VERSION_HEX >= 0x030700A2
-    tmp_type = tstate->exc_state.exc_type;
-    tmp_value = tstate->exc_state.exc_value;
-    tmp_tb = tstate->exc_state.exc_traceback;
-    tstate->exc_state.exc_type = type;
-    tstate->exc_state.exc_value = value;
-    tstate->exc_state.exc_traceback = tb;
+    #if CYTHON_USE_EXC_INFO_STACK
+    _PyErr_StackItem *exc_info = tstate->exc_info;
+    tmp_type = exc_info->exc_type;
+    tmp_value = exc_info->exc_value;
+    tmp_tb = exc_info->exc_traceback;
+    exc_info->exc_type = type;
+    exc_info->exc_value = value;
+    exc_info->exc_traceback = tb;
     #else
     tmp_type = tstate->exc_type;
     tmp_value = tstate->exc_value;
@@ -53908,7 +52341,7 @@ static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject
 #endif
 
 /* FastTypeChecks */
-      #if CYTHON_COMPILING_IN_CPYTHON
+#if CYTHON_COMPILING_IN_CPYTHON
 static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) {
     while (a) {
         a = a->tp_base;
@@ -53963,14 +52396,42 @@ static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err,
     return res;
 }
 #endif
+static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) {
+    Py_ssize_t i, n;
+    assert(PyExceptionClass_Check(exc_type));
+    n = PyTuple_GET_SIZE(tuple);
+#if PY_MAJOR_VERSION >= 3
+    for (i=0; i<n; i++) {
+        if (exc_type == PyTuple_GET_ITEM(tuple, i)) return 1;
+    }
+#endif
+    for (i=0; i<n; i++) {
+        PyObject *t = PyTuple_GET_ITEM(tuple, i);
+        #if PY_MAJOR_VERSION < 3
+        if (likely(exc_type == t)) return 1;
+        #endif
+        if (likely(PyExceptionClass_Check(t))) {
+            if (__Pyx_inner_PyErr_GivenExceptionMatches2(exc_type, NULL, t)) return 1;
+        } else {
+        }
+    }
+    return 0;
+}
 static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject* exc_type) {
     if (likely(err == exc_type)) return 1;
     if (likely(PyExceptionClass_Check(err))) {
-        return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type);
+        if (likely(PyExceptionClass_Check(exc_type))) {
+            return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type);
+        } else if (likely(PyTuple_Check(exc_type))) {
+            return __Pyx_PyErr_GivenExceptionMatchesTuple(err, exc_type);
+        } else {
+        }
     }
     return PyErr_GivenExceptionMatches(err, exc_type);
 }
 static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *exc_type1, PyObject *exc_type2) {
+    assert(PyExceptionClass_Check(exc_type1));
+    assert(PyExceptionClass_Check(exc_type2));
     if (likely(err == exc_type1 || err == exc_type2)) return 1;
     if (likely(PyExceptionClass_Check(err))) {
         return __Pyx_inner_PyErr_GivenExceptionMatches2(err, exc_type1, exc_type2);
@@ -53980,11 +52441,12 @@ static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObj
 #endif
 
 /* GetException */
-      #if CYTHON_FAST_THREAD_STATE
-static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
+#if CYTHON_FAST_THREAD_STATE
+static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb)
 #else
-static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
+static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
 #endif
+{
     PyObject *local_type, *local_value, *local_tb;
 #if CYTHON_FAST_THREAD_STATE
     PyObject *tmp_type, *tmp_value, *tmp_tb;
@@ -54017,13 +52479,16 @@ static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
     *value = local_value;
     *tb = local_tb;
 #if CYTHON_FAST_THREAD_STATE
-    #if PY_VERSION_HEX >= 0x030700A2
-    tmp_type = tstate->exc_state.exc_type;
-    tmp_value = tstate->exc_state.exc_value;
-    tmp_tb = tstate->exc_state.exc_traceback;
-    tstate->exc_state.exc_type = local_type;
-    tstate->exc_state.exc_value = local_value;
-    tstate->exc_state.exc_traceback = local_tb;
+    #if CYTHON_USE_EXC_INFO_STACK
+    {
+        _PyErr_StackItem *exc_info = tstate->exc_info;
+        tmp_type = exc_info->exc_type;
+        tmp_value = exc_info->exc_value;
+        tmp_tb = exc_info->exc_traceback;
+        exc_info->exc_type = local_type;
+        exc_info->exc_value = local_value;
+        exc_info->exc_traceback = local_tb;
+    }
     #else
     tmp_type = tstate->exc_type;
     tmp_value = tstate->exc_value;
@@ -54049,21 +52514,168 @@ bad:
     return -1;
 }
 
+/* GetItemInt */
+static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
+    PyObject *r;
+    if (!j) return NULL;
+    r = PyObject_GetItem(o, j);
+    Py_DECREF(j);
+    return r;
+}
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
+                                                              CYTHON_NCP_UNUSED int wraparound,
+                                                              CYTHON_NCP_UNUSED int boundscheck) {
+#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+    Py_ssize_t wrapped_i = i;
+    if (wraparound & unlikely(i < 0)) {
+        wrapped_i += PyList_GET_SIZE(o);
+    }
+    if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) {
+        PyObject *r = PyList_GET_ITEM(o, wrapped_i);
+        Py_INCREF(r);
+        return r;
+    }
+    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
+#else
+    return PySequence_GetItem(o, i);
+#endif
+}
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i,
+                                                              CYTHON_NCP_UNUSED int wraparound,
+                                                              CYTHON_NCP_UNUSED int boundscheck) {
+#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+    Py_ssize_t wrapped_i = i;
+    if (wraparound & unlikely(i < 0)) {
+        wrapped_i += PyTuple_GET_SIZE(o);
+    }
+    if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) {
+        PyObject *r = PyTuple_GET_ITEM(o, wrapped_i);
+        Py_INCREF(r);
+        return r;
+    }
+    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
+#else
+    return PySequence_GetItem(o, i);
+#endif
+}
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list,
+                                                     CYTHON_NCP_UNUSED int wraparound,
+                                                     CYTHON_NCP_UNUSED int boundscheck) {
+#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS
+    if (is_list || PyList_CheckExact(o)) {
+        Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o);
+        if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) {
+            PyObject *r = PyList_GET_ITEM(o, n);
+            Py_INCREF(r);
+            return r;
+        }
+    }
+    else if (PyTuple_CheckExact(o)) {
+        Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o);
+        if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) {
+            PyObject *r = PyTuple_GET_ITEM(o, n);
+            Py_INCREF(r);
+            return r;
+        }
+    } else {
+        PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
+        if (likely(m && m->sq_item)) {
+            if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
+                Py_ssize_t l = m->sq_length(o);
+                if (likely(l >= 0)) {
+                    i += l;
+                } else {
+                    if (!PyErr_ExceptionMatches(PyExc_OverflowError))
+                        return NULL;
+                    PyErr_Clear();
+                }
+            }
+            return m->sq_item(o, i);
+        }
+    }
+#else
+    if (is_list || PySequence_Check(o)) {
+        return PySequence_GetItem(o, i);
+    }
+#endif
+    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
+}
+
+/* PyErrExceptionMatches */
+#if CYTHON_FAST_THREAD_STATE
+static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) {
+    Py_ssize_t i, n;
+    n = PyTuple_GET_SIZE(tuple);
+#if PY_MAJOR_VERSION >= 3
+    for (i=0; i<n; i++) {
+        if (exc_type == PyTuple_GET_ITEM(tuple, i)) return 1;
+    }
+#endif
+    for (i=0; i<n; i++) {
+        if (__Pyx_PyErr_GivenExceptionMatches(exc_type, PyTuple_GET_ITEM(tuple, i))) return 1;
+    }
+    return 0;
+}
+static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err) {
+    PyObject *exc_type = tstate->curexc_type;
+    if (exc_type == err) return 1;
+    if (unlikely(!exc_type)) return 0;
+    if (unlikely(PyTuple_Check(err)))
+        return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err);
+    return __Pyx_PyErr_GivenExceptionMatches(exc_type, err);
+}
+#endif
+
+/* SwapException */
+#if CYTHON_FAST_THREAD_STATE
+static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+    #if CYTHON_USE_EXC_INFO_STACK
+    _PyErr_StackItem *exc_info = tstate->exc_info;
+    tmp_type = exc_info->exc_type;
+    tmp_value = exc_info->exc_value;
+    tmp_tb = exc_info->exc_traceback;
+    exc_info->exc_type = *type;
+    exc_info->exc_value = *value;
+    exc_info->exc_traceback = *tb;
+    #else
+    tmp_type = tstate->exc_type;
+    tmp_value = tstate->exc_value;
+    tmp_tb = tstate->exc_traceback;
+    tstate->exc_type = *type;
+    tstate->exc_value = *value;
+    tstate->exc_traceback = *tb;
+    #endif
+    *type = tmp_type;
+    *value = tmp_value;
+    *tb = tmp_tb;
+}
+#else
+static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) {
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+    PyErr_GetExcInfo(&tmp_type, &tmp_value, &tmp_tb);
+    PyErr_SetExcInfo(*type, *value, *tb);
+    *type = tmp_type;
+    *value = tmp_value;
+    *tb = tmp_tb;
+}
+#endif
+
 /* RaiseTooManyValuesToUnpack */
-        static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) {
+static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) {
     PyErr_Format(PyExc_ValueError,
                  "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected);
 }
 
 /* RaiseNeedMoreValuesToUnpack */
-        static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
+static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
     PyErr_Format(PyExc_ValueError,
                  "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack",
                  index, (index == 1) ? "" : "s");
 }
 
 /* IterFinish */
-        static CYTHON_INLINE int __Pyx_IterFinish(void) {
+static CYTHON_INLINE int __Pyx_IterFinish(void) {
 #if CYTHON_FAST_THREAD_STATE
     PyThreadState *tstate = __Pyx_PyThreadState_Current;
     PyObject* exc_type = tstate->curexc_type;
@@ -54098,7 +52710,7 @@ bad:
 }
 
 /* UnpackItemEndCheck */
-        static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) {
+static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) {
     if (unlikely(retval)) {
         Py_DECREF(retval);
         __Pyx_RaiseTooManyValuesError(expected);
@@ -54110,7 +52722,7 @@ bad:
 }
 
 /* IterNext */
-        static PyObject *__Pyx_PyIter_Next2Default(PyObject* defval) {
+static PyObject *__Pyx_PyIter_Next2Default(PyObject* defval) {
     PyObject* exc_type;
     __Pyx_PyThreadState_declare
     __Pyx_PyThreadState_assign
@@ -54165,7 +52777,7 @@ static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject* iterator, PyObject*
 }
 
 /* PyObject_GenericGetAttrNoDict */
-        #if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000
+#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000
 static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) {
     PyErr_Format(PyExc_AttributeError,
 #if PY_MAJOR_VERSION >= 3
@@ -54205,7 +52817,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj
 #endif
 
 /* PyObject_GenericGetAttr */
-        #if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000
+#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000
 static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name) {
     if (unlikely(Py_TYPE(obj)->tp_dictoffset)) {
         return PyObject_GenericGetAttr(obj, attr_name);
@@ -54215,7 +52827,7 @@ static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_nam
 #endif
 
 /* SetVTable */
-        static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
+static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
 #if PY_VERSION_HEX >= 0x02070000
     PyObject *ob = PyCapsule_New(vtable, 0, 0);
 #else
@@ -54233,7 +52845,7 @@ bad:
 }
 
 /* SetupReduce */
-        static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) {
+static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) {
   int ret;
   PyObject *name_attr;
   name_attr = __Pyx_PyObject_GetAttrStr(meth, __pyx_n_s_name);
@@ -54309,7 +52921,7 @@ GOOD:
 }
 
 /* Import */
-        static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
     PyObject *empty_list = 0;
     PyObject *module = 0;
     PyObject *global_dict = 0;
@@ -54356,7 +52968,7 @@ GOOD:
             if (!py_level)
                 goto bad;
             module = PyObject_CallFunctionObjArgs(py_import,
-                name, global_dict, empty_dict, list, py_level, NULL);
+                name, global_dict, empty_dict, list, py_level, (PyObject *)NULL);
             Py_DECREF(py_level);
             #else
             module = PyImport_ImportModuleLevelObject(
@@ -54374,7 +52986,7 @@ bad:
 }
 
 /* CalculateMetaclass */
-        static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases) {
+static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases) {
     Py_ssize_t i, nbases = PyTuple_GET_SIZE(bases);
     for (i=0; i < nbases; i++) {
         PyTypeObject *tmptype;
@@ -54413,7 +53025,7 @@ bad:
 }
 
 /* Py3ClassCreate */
-        static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name,
+static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name,
                                            PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc) {
     PyObject *ns;
     if (metaclass) {
@@ -54480,14 +53092,14 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
 }
 
 /* ClassMethod */
-        static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
+static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
 #if CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM <= 0x05080000
     if (PyObject_TypeCheck(method, &PyWrapperDescr_Type)) {
         return PyClassMethod_New(method);
     }
 #else
 #if CYTHON_COMPILING_IN_PYSTON || CYTHON_COMPILING_IN_PYPY
-    if (PyMethodDescr_Check(method)) {
+    if (PyMethodDescr_Check(method))
 #else
     static PyTypeObject *methoddescr_type = NULL;
     if (methoddescr_type == NULL) {
@@ -54496,8 +53108,9 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
        methoddescr_type = Py_TYPE(meth);
        Py_DECREF(meth);
     }
-    if (__Pyx_TypeCheck(method, methoddescr_type)) {
+    if (__Pyx_TypeCheck(method, methoddescr_type))
 #endif
+    {
         PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
         #if PY_VERSION_HEX < 0x03020000
         PyTypeObject *d_type = descr->d_type;
@@ -54514,7 +53127,7 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
         return PyClassMethod_New(method);
     }
 #ifdef __Pyx_CyFunction_USED
-    else if (__Pyx_TypeCheck(method, __pyx_CyFunctionType)) {
+    else if (__Pyx_CyFunction_Check(method)) {
         return PyClassMethod_New(method);
     }
 #endif
@@ -54524,41 +53137,18 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
     return NULL;
 }
 
-/* PyErrExceptionMatches */
-          #if CYTHON_FAST_THREAD_STATE
-static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) {
-    Py_ssize_t i, n;
-    n = PyTuple_GET_SIZE(tuple);
-#if PY_MAJOR_VERSION >= 3
-    for (i=0; i<n; i++) {
-        if (exc_type == PyTuple_GET_ITEM(tuple, i)) return 1;
-    }
-#endif
-    for (i=0; i<n; i++) {
-        if (__Pyx_PyErr_GivenExceptionMatches(exc_type, PyTuple_GET_ITEM(tuple, i))) return 1;
-    }
-    return 0;
-}
-static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err) {
-    PyObject *exc_type = tstate->curexc_type;
-    if (exc_type == err) return 1;
-    if (unlikely(!exc_type)) return 0;
-    if (unlikely(PyTuple_Check(err)))
-        return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err);
-    return __Pyx_PyErr_GivenExceptionMatches(exc_type, err);
-}
-#endif
-
 /* GetNameInClass */
-          static PyObject *__Pyx_GetGlobalNameAfterAttributeLookup(PyObject *name) {
+static PyObject *__Pyx_GetGlobalNameAfterAttributeLookup(PyObject *name) {
+    PyObject *result;
     __Pyx_PyThreadState_declare
     __Pyx_PyThreadState_assign
     if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError)))
         return NULL;
     __Pyx_PyErr_Clear();
-    return __Pyx_GetModuleGlobalName(name);
+    __Pyx_GetModuleGlobalNameUncached(result, name);
+    return result;
 }
-static PyObject *__Pyx_GetNameInClass(PyObject *nmspace, PyObject *name) {
+static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name) {
     PyObject *result;
     result = __Pyx_PyObject_GetAttrStr(nmspace, name);
     if (!result) {
@@ -54568,7 +53158,7 @@ static PyObject *__Pyx_GetNameInClass(PyObject *nmspace, PyObject *name) {
 }
 
 /* FetchCommonType */
-          static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
+static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
     PyObject* fake_module;
     PyTypeObject* cached_type = NULL;
     fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI);
@@ -54607,7 +53197,7 @@ bad:
 }
 
 /* CythonFunction */
-          #include <structmember.h>
+#include <structmember.h>
 static PyObject *
 __Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure)
 {
@@ -54629,7 +53219,7 @@ __Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure
     return op->func_doc;
 }
 static int
-__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value)
+__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context)
 {
     PyObject *tmp = op->func_doc;
     if (value == NULL) {
@@ -54641,7 +53231,7 @@ __Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value)
     return 0;
 }
 static PyObject *
-__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op)
+__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
 {
     if (unlikely(op->func_name == NULL)) {
 #if PY_MAJOR_VERSION >= 3
@@ -54656,14 +53246,15 @@ __Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op)
     return op->func_name;
 }
 static int
-__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value)
+__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context)
 {
     PyObject *tmp;
 #if PY_MAJOR_VERSION >= 3
-    if (unlikely(value == NULL || !PyUnicode_Check(value))) {
+    if (unlikely(value == NULL || !PyUnicode_Check(value)))
 #else
-    if (unlikely(value == NULL || !PyString_Check(value))) {
+    if (unlikely(value == NULL || !PyString_Check(value)))
 #endif
+    {
         PyErr_SetString(PyExc_TypeError,
                         "__name__ must be set to a string object");
         return -1;
@@ -54675,20 +53266,21 @@ __Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value)
     return 0;
 }
 static PyObject *
-__Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op)
+__Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
 {
     Py_INCREF(op->func_qualname);
     return op->func_qualname;
 }
 static int
-__Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value)
+__Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context)
 {
     PyObject *tmp;
 #if PY_MAJOR_VERSION >= 3
-    if (unlikely(value == NULL || !PyUnicode_Check(value))) {
+    if (unlikely(value == NULL || !PyUnicode_Check(value)))
 #else
-    if (unlikely(value == NULL || !PyString_Check(value))) {
+    if (unlikely(value == NULL || !PyString_Check(value)))
 #endif
+    {
         PyErr_SetString(PyExc_TypeError,
                         "__qualname__ must be set to a string object");
         return -1;
@@ -54710,7 +53302,7 @@ __Pyx_CyFunction_get_self(__pyx_CyFunctionObject *m, CYTHON_UNUSED void *closure
     return self;
 }
 static PyObject *
-__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op)
+__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
 {
     if (unlikely(op->func_dict == NULL)) {
         op->func_dict = PyDict_New();
@@ -54721,7 +53313,7 @@ __Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op)
     return op->func_dict;
 }
 static int
-__Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value)
+__Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context)
 {
     PyObject *tmp;
     if (unlikely(value == NULL)) {
@@ -54741,19 +53333,19 @@ __Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value)
     return 0;
 }
 static PyObject *
-__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op)
+__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
 {
     Py_INCREF(op->func_globals);
     return op->func_globals;
 }
 static PyObject *
-__Pyx_CyFunction_get_closure(CYTHON_UNUSED __pyx_CyFunctionObject *op)
+__Pyx_CyFunction_get_closure(CYTHON_UNUSED __pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
 {
     Py_INCREF(Py_None);
     return Py_None;
 }
 static PyObject *
-__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op)
+__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
 {
     PyObject* result = (op->func_code) ? op->func_code : Py_None;
     Py_INCREF(result);
@@ -54782,7 +53374,7 @@ __Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) {
     return result;
 }
 static int
-__Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value) {
+__Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) {
     PyObject* tmp;
     if (!value) {
         value = Py_None;
@@ -54798,7 +53390,7 @@ __Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value) {
     return 0;
 }
 static PyObject *
-__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op) {
+__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) {
     PyObject* result = op->defaults_tuple;
     if (unlikely(!result)) {
         if (op->defaults_getter) {
@@ -54812,7 +53404,7 @@ __Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op) {
     return result;
 }
 static int
-__Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value) {
+__Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) {
     PyObject* tmp;
     if (!value) {
         value = Py_None;
@@ -54828,7 +53420,7 @@ __Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value) {
     return 0;
 }
 static PyObject *
-__Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op) {
+__Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) {
     PyObject* result = op->defaults_kwdict;
     if (unlikely(!result)) {
         if (op->defaults_getter) {
@@ -54842,7 +53434,7 @@ __Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op) {
     return result;
 }
 static int
-__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value) {
+__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) {
     PyObject* tmp;
     if (!value || value == Py_None) {
         value = NULL;
@@ -54858,7 +53450,7 @@ __Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value) {
     return 0;
 }
 static PyObject *
-__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op) {
+__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) {
     PyObject* result = op->func_annotations;
     if (unlikely(!result)) {
         result = PyDict_New();
@@ -55038,7 +53630,7 @@ static PyObject * __Pyx_CyFunction_CallMethod(PyObject *func, PyObject *self, Py
             return (*meth)(self, arg);
         break;
     case METH_VARARGS | METH_KEYWORDS:
-        return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
+        return (*(PyCFunctionWithKeywords)(void*)meth)(self, arg, kw);
     case METH_NOARGS:
         if (likely(kw == NULL || PyDict_Size(kw) == 0)) {
             size = PyTuple_GET_SIZE(arg);
@@ -55201,8 +53793,8 @@ static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *func, Py
 }
 
 /* CLineInTraceback */
-              #ifndef CYTHON_CLINE_IN_TRACEBACK
-static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_line) {
+#ifndef CYTHON_CLINE_IN_TRACEBACK
+static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) {
     PyObject *use_cline;
     PyObject *ptype, *pvalue, *ptraceback;
 #if CYTHON_COMPILING_IN_CPYTHON
@@ -55215,7 +53807,9 @@ static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_li
 #if CYTHON_COMPILING_IN_CPYTHON
     cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime);
     if (likely(cython_runtime_dict)) {
-      use_cline = __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback);
+        __PYX_PY_DICT_LOOKUP_IF_MODIFIED(
+            use_cline, *cython_runtime_dict,
+            __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback))
     } else
 #endif
     {
@@ -55232,7 +53826,7 @@ static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_li
         c_line = 0;
         PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False);
     }
-    else if (PyObject_Not(use_cline) != 0) {
+    else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) {
         c_line = 0;
     }
     __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback);
@@ -55241,7 +53835,7 @@ static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_li
 #endif
 
 /* CodeObjectCache */
-              static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
+static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
     int start = 0, mid = 0, end = count - 1;
     if (end >= 0 && code_line > entries[end].code_line) {
         return count;
@@ -55321,7 +53915,7 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
 }
 
 /* AddTraceback */
-              #include "compile.h"
+#include "compile.h"
 #include "frameobject.h"
 #include "traceback.h"
 static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
@@ -55406,7 +54000,7 @@ bad:
 }
 
 /* CIntFromPyVerify */
-              #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\
+#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\
     __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0)
 #define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\
     __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1)
@@ -55428,8 +54022,8 @@ bad:
     }
 
 /* CIntToPy */
-              static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) {
-    const int neg_one = (int) -1, const_zero = (int) 0;
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) {
+    const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0;
     const int is_unsigned = neg_one > const_zero;
     if (is_unsigned) {
         if (sizeof(int) < sizeof(long)) {
@@ -55459,8 +54053,39 @@ bad:
 }
 
 /* CIntToPy */
-              static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint64_t(uint64_t value) {
-    const uint64_t neg_one = (uint64_t) -1, const_zero = (uint64_t) 0;
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int64_t(int64_t value) {
+    const int64_t neg_one = (int64_t) ((int64_t) 0 - (int64_t) 1), const_zero = (int64_t) 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (is_unsigned) {
+        if (sizeof(int64_t) < sizeof(long)) {
+            return PyInt_FromLong((long) value);
+        } else if (sizeof(int64_t) <= sizeof(unsigned long)) {
+            return PyLong_FromUnsignedLong((unsigned long) value);
+#ifdef HAVE_LONG_LONG
+        } else if (sizeof(int64_t) <= sizeof(unsigned PY_LONG_LONG)) {
+            return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
+#endif
+        }
+    } else {
+        if (sizeof(int64_t) <= sizeof(long)) {
+            return PyInt_FromLong((long) value);
+#ifdef HAVE_LONG_LONG
+        } else if (sizeof(int64_t) <= sizeof(PY_LONG_LONG)) {
+            return PyLong_FromLongLong((PY_LONG_LONG) value);
+#endif
+        }
+    }
+    {
+        int one = 1; int little = (int)*(unsigned char *)&one;
+        unsigned char *bytes = (unsigned char *)&value;
+        return _PyLong_FromByteArray(bytes, sizeof(int64_t),
+                                     little, !is_unsigned);
+    }
+}
+
+/* CIntToPy */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint64_t(uint64_t value) {
+    const uint64_t neg_one = (uint64_t) ((uint64_t) 0 - (uint64_t) 1), const_zero = (uint64_t) 0;
     const int is_unsigned = neg_one > const_zero;
     if (is_unsigned) {
         if (sizeof(uint64_t) < sizeof(long)) {
@@ -55490,8 +54115,8 @@ bad:
 }
 
 /* CIntToPy */
-              static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint32_t(uint32_t value) {
-    const uint32_t neg_one = (uint32_t) -1, const_zero = (uint32_t) 0;
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint32_t(uint32_t value) {
+    const uint32_t neg_one = (uint32_t) ((uint32_t) 0 - (uint32_t) 1), const_zero = (uint32_t) 0;
     const int is_unsigned = neg_one > const_zero;
     if (is_unsigned) {
         if (sizeof(uint32_t) < sizeof(long)) {
@@ -55521,24 +54146,24 @@ bad:
 }
 
 /* CIntToPy */
-              static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int64_t(int64_t value) {
-    const int64_t neg_one = (int64_t) -1, const_zero = (int64_t) 0;
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) {
+    const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0;
     const int is_unsigned = neg_one > const_zero;
     if (is_unsigned) {
-        if (sizeof(int64_t) < sizeof(long)) {
+        if (sizeof(long) < sizeof(long)) {
             return PyInt_FromLong((long) value);
-        } else if (sizeof(int64_t) <= sizeof(unsigned long)) {
+        } else if (sizeof(long) <= sizeof(unsigned long)) {
             return PyLong_FromUnsignedLong((unsigned long) value);
 #ifdef HAVE_LONG_LONG
-        } else if (sizeof(int64_t) <= sizeof(unsigned PY_LONG_LONG)) {
+        } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) {
             return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
 #endif
         }
     } else {
-        if (sizeof(int64_t) <= sizeof(long)) {
+        if (sizeof(long) <= sizeof(long)) {
             return PyInt_FromLong((long) value);
 #ifdef HAVE_LONG_LONG
-        } else if (sizeof(int64_t) <= sizeof(PY_LONG_LONG)) {
+        } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) {
             return PyLong_FromLongLong((PY_LONG_LONG) value);
 #endif
         }
@@ -55546,14 +54171,14 @@ bad:
     {
         int one = 1; int little = (int)*(unsigned char *)&one;
         unsigned char *bytes = (unsigned char *)&value;
-        return _PyLong_FromByteArray(bytes, sizeof(int64_t),
+        return _PyLong_FromByteArray(bytes, sizeof(long),
                                      little, !is_unsigned);
     }
 }
 
 /* CIntToPy */
-              static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int32_t(int32_t value) {
-    const int32_t neg_one = (int32_t) -1, const_zero = (int32_t) 0;
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int32_t(int32_t value) {
+    const int32_t neg_one = (int32_t) ((int32_t) 0 - (int32_t) 1), const_zero = (int32_t) 0;
     const int is_unsigned = neg_one > const_zero;
     if (is_unsigned) {
         if (sizeof(int32_t) < sizeof(long)) {
@@ -55583,8 +54208,8 @@ bad:
 }
 
 /* CIntFromPy */
-              static CYTHON_INLINE size_t __Pyx_PyInt_As_size_t(PyObject *x) {
-    const size_t neg_one = (size_t) -1, const_zero = (size_t) 0;
+static CYTHON_INLINE size_t __Pyx_PyInt_As_size_t(PyObject *x) {
+    const size_t neg_one = (size_t) ((size_t) 0 - (size_t) 1), const_zero = (size_t) 0;
     const int is_unsigned = neg_one > const_zero;
 #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
@@ -55772,8 +54397,8 @@ raise_neg_overflow:
 }
 
 /* CIntFromPy */
-              static CYTHON_INLINE int64_t __Pyx_PyInt_As_int64_t(PyObject *x) {
-    const int64_t neg_one = (int64_t) -1, const_zero = (int64_t) 0;
+static CYTHON_INLINE int64_t __Pyx_PyInt_As_int64_t(PyObject *x) {
+    const int64_t neg_one = (int64_t) ((int64_t) 0 - (int64_t) 1), const_zero = (int64_t) 0;
     const int is_unsigned = neg_one > const_zero;
 #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
@@ -55961,8 +54586,8 @@ raise_neg_overflow:
 }
 
 /* CIntFromPy */
-              static CYTHON_INLINE uint64_t __Pyx_PyInt_As_uint64_t(PyObject *x) {
-    const uint64_t neg_one = (uint64_t) -1, const_zero = (uint64_t) 0;
+static CYTHON_INLINE uint64_t __Pyx_PyInt_As_uint64_t(PyObject *x) {
+    const uint64_t neg_one = (uint64_t) ((uint64_t) 0 - (uint64_t) 1), const_zero = (uint64_t) 0;
     const int is_unsigned = neg_one > const_zero;
 #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
@@ -56150,8 +54775,8 @@ raise_neg_overflow:
 }
 
 /* CIntFromPy */
-              static CYTHON_INLINE int32_t __Pyx_PyInt_As_int32_t(PyObject *x) {
-    const int32_t neg_one = (int32_t) -1, const_zero = (int32_t) 0;
+static CYTHON_INLINE int32_t __Pyx_PyInt_As_int32_t(PyObject *x) {
+    const int32_t neg_one = (int32_t) ((int32_t) 0 - (int32_t) 1), const_zero = (int32_t) 0;
     const int is_unsigned = neg_one > const_zero;
 #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
@@ -56339,8 +54964,8 @@ raise_neg_overflow:
 }
 
 /* CIntFromPy */
-              static CYTHON_INLINE uint32_t __Pyx_PyInt_As_uint32_t(PyObject *x) {
-    const uint32_t neg_one = (uint32_t) -1, const_zero = (uint32_t) 0;
+static CYTHON_INLINE uint32_t __Pyx_PyInt_As_uint32_t(PyObject *x) {
+    const uint32_t neg_one = (uint32_t) ((uint32_t) 0 - (uint32_t) 1), const_zero = (uint32_t) 0;
     const int is_unsigned = neg_one > const_zero;
 #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
@@ -56528,8 +55153,8 @@ raise_neg_overflow:
 }
 
 /* CIntFromPy */
-              static CYTHON_INLINE time_t __Pyx_PyInt_As_time_t(PyObject *x) {
-    const time_t neg_one = (time_t) -1, const_zero = (time_t) 0;
+static CYTHON_INLINE time_t __Pyx_PyInt_As_time_t(PyObject *x) {
+    const time_t neg_one = (time_t) ((time_t) 0 - (time_t) 1), const_zero = (time_t) 0;
     const int is_unsigned = neg_one > const_zero;
 #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
@@ -56716,40 +55341,9 @@ raise_neg_overflow:
     return (time_t) -1;
 }
 
-/* CIntToPy */
-              static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) {
-    const long neg_one = (long) -1, const_zero = (long) 0;
-    const int is_unsigned = neg_one > const_zero;
-    if (is_unsigned) {
-        if (sizeof(long) < sizeof(long)) {
-            return PyInt_FromLong((long) value);
-        } else if (sizeof(long) <= sizeof(unsigned long)) {
-            return PyLong_FromUnsignedLong((unsigned long) value);
-#ifdef HAVE_LONG_LONG
-        } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) {
-            return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
-#endif
-        }
-    } else {
-        if (sizeof(long) <= sizeof(long)) {
-            return PyInt_FromLong((long) value);
-#ifdef HAVE_LONG_LONG
-        } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) {
-            return PyLong_FromLongLong((PY_LONG_LONG) value);
-#endif
-        }
-    }
-    {
-        int one = 1; int little = (int)*(unsigned char *)&one;
-        unsigned char *bytes = (unsigned char *)&value;
-        return _PyLong_FromByteArray(bytes, sizeof(long),
-                                     little, !is_unsigned);
-    }
-}
-
 /* CIntFromPy */
-              static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) {
-    const long neg_one = (long) -1, const_zero = (long) 0;
+static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) {
+    const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0;
     const int is_unsigned = neg_one > const_zero;
 #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
@@ -56937,8 +55531,8 @@ raise_neg_overflow:
 }
 
 /* CIntFromPy */
-              static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) {
-    const int neg_one = (int) -1, const_zero = (int) 0;
+static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) {
+    const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0;
     const int is_unsigned = neg_one > const_zero;
 #if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
@@ -57126,7 +55720,7 @@ raise_neg_overflow:
 }
 
 /* CheckBinaryVersion */
-              static int __Pyx_check_binary_version(void) {
+static int __Pyx_check_binary_version(void) {
     char ctversion[4], rtversion[4];
     PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION);
     PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion());
@@ -57142,7 +55736,7 @@ raise_neg_overflow:
 }
 
 /* FunctionExport */
-              static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig) {
+static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig) {
     PyObject *d = 0;
     PyObject *cobj = 0;
     union {
@@ -57179,7 +55773,7 @@ bad:
 }
 
 /* InitStrings */
-              static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
     while (t->p) {
         #if PY_MAJOR_VERSION < 3
         if (t->is_unicode) {
@@ -57288,6 +55882,13 @@ static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
    if (is_true | (x == Py_False) | (x == Py_None)) return is_true;
    else return PyObject_IsTrue(x);
 }
+static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) {
+    int retval;
+    if (unlikely(!x)) return -1;
+    retval = __Pyx_PyObject_IsTrue(x);
+    Py_DECREF(x);
+    return retval;
+}
 static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) {
 #if PY_MAJOR_VERSION >= 3
     if (PyLong_Check(result)) {
@@ -57365,7 +55966,7 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
     if (sizeof(Py_ssize_t) >= sizeof(long))
         return PyInt_AS_LONG(b);
     else
-        return PyInt_AsSsize_t(x);
+        return PyInt_AsSsize_t(b);
   }
 #endif
   if (likely(PyLong_CheckExact(b))) {
index f571f9d..3021cc6 100644 (file)
@@ -108,6 +108,8 @@ cdef class _SymbolTable(object):
 
   cpdef void write_text(self, filename) except *
 
+  cpdef bytes write_to_string(self)
+
 
 cdef class _EncodeMapperSymbolTable(_SymbolTable):
 
@@ -153,6 +155,8 @@ cdef _MutableFstSymbolTable _init_MutableFstSymbolTable(fst.SymbolTable *table,
 cdef SymbolTable _init_SymbolTable(fst.SymbolTable *table)
 
 
+cpdef _SymbolTable _read_SymbolTable_from_string(state)
+
 
 cdef class SymbolTableIterator(object):
 
@@ -206,6 +210,14 @@ cdef class _Fst(object):
 
   cdef shared_ptr[fst.FstClass] _fst
 
+  # Google-only...
+  @staticmethod
+  cdef string _server_render_svg(const string &)
+  # ...Google-only.
+
+  @staticmethod
+  cdef string _local_render_svg(const string &)
+
   cpdef string arc_type(self)
 
   cpdef ArcIterator arcs(self, int64 state)
@@ -326,7 +338,7 @@ cdef class _MutableFst(_Fst):
   cdef void _union(self, _Fst ifst) except *
 
 
-# Fst construction helpers.
+# Construction helpers.
 
 
 cdef _Fst _init_Fst(FstClass_ptr tfst)
@@ -339,7 +351,7 @@ cdef _MutableFst _create_Fst(arc_type=?)
 
 cpdef _Fst _read(filename)
 
-cpdef _Fst _read_from_string(state)
+cpdef _Fst _read_Fst_from_string(state)
 
 
 # Iterators.
index b0e1a4b..6a26c5b 100644 (file)
@@ -81,15 +81,19 @@ from cython.operator cimport dereference as deref  # *foo
 from cython.operator cimport preincrement as inc   # ++foo
 
 # Python imports.
-import atexit
 import numbers
 import subprocess
 import logging
 
-
-# TODO(kbg): Figure out how to access static class variables so I don't have
-# to do it this way.
-kNoSymbol = -1
+# Google-only...
+# This only works, and is only needed, inside of Colab.
+try:
+  from colabtools import frontend
+  from colabtools import stubby
+  from google3.visualization.graphviz_server.proto import graphviz_server_pb2
+except ImportError:
+  pass
+# ...Google-only.
 
 
 ## Custom exceptions.
@@ -670,6 +674,11 @@ cdef class _SymbolTable(object):
   def __iter__(self):
     return SymbolTableIterator(self)
 
+  # Registers the class for pickling.
+
+  def __reduce__(self):
+    return (_read_SymbolTable_from_string, (self.write_to_string(),))
+
   cpdef int64 available_key(self):
     """
     available_key(self)
@@ -812,6 +821,25 @@ cdef class _SymbolTable(object):
     if not self._table.WriteText(tostring(filename)):
       raise FstIOError("Write failed: {!r}".format(filename))
 
+  cpdef bytes write_to_string(self):
+    """
+    write_to_string(self)
+
+    Serializes SymbolTable to a string.
+
+    Returns:
+      A bytestring.
+
+    Raises:
+      FstIOError: Write to string failed.
+
+    See also: `read_from_string`.
+    """
+    cdef stringstream sstrm
+    if not self._table.Write(sstrm):
+      raise FstIOError("Write to string failed")
+    return sstrm.str()
+
 
 cdef class _EncodeMapperSymbolTable(_SymbolTable):
 
@@ -863,7 +891,7 @@ cdef class _MutableSymbolTable(_SymbolTable):
   constructor and implementations of all methods of the wrapped SymbolTable.
   """
 
-  cpdef int64 add_symbol(self, symbol, int64 key=kNoSymbol):
+  cpdef int64 add_symbol(self, symbol, int64 key=fst.kNoSymbol):
     """
     add_symbol(self, symbol, key=NO_SYMBOL)
 
@@ -881,7 +909,7 @@ cdef class _MutableSymbolTable(_SymbolTable):
       The integer key of the new symbol.
     """
     cdef string symbol_string = tostring(symbol)
-    if key != kNoSymbol:
+    if key != fst.kNoSymbol:
       return self._table.AddSymbol(symbol_string, key)
     else:
       return self._table.AddSymbol(symbol_string)
@@ -956,10 +984,11 @@ cdef class SymbolTable(_MutableSymbolTable):
 
     See also: `SymbolTable.read_fst`, `SymbolTable.read_text`.
     """
-    cdef fst.SymbolTable *tsyms = fst.SymbolTable.Read(tostring(filename))
-    if tsyms == NULL:
+    cdef unique_ptr[fst.SymbolTable] syms
+    syms.reset(fst.SymbolTable.Read(tostring(filename)))
+    if syms.get() == NULL:
       raise FstIOError("Read failed: {!r}".format(filename))
-    return _init_SymbolTable(tsyms)
+    return _init_SymbolTable(syms.release())
 
   @classmethod
   def read_text(cls, filename, bool allow_negative_labels=False):
@@ -982,11 +1011,11 @@ cdef class SymbolTable(_MutableSymbolTable):
     """
     cdef unique_ptr[fst.SymbolTableTextOptions] opts
     opts.reset(new fst.SymbolTableTextOptions(allow_negative_labels))
-    cdef fst.SymbolTable *tsyms = fst.SymbolTable.ReadText(tostring(filename),
-                                                           deref(opts))
-    if tsyms == NULL:
+    cdef unique_ptr[fst.SymbolTable] syms
+    syms.reset(fst.SymbolTable.ReadText(tostring(filename), deref(opts)))
+    if syms.get() == NULL:
       raise FstIOError("Read failed: {!r}".format(filename))
-    return _init_SymbolTable(tsyms)
+    return _init_SymbolTable(syms.release())
 
   @classmethod
   def read_fst(cls, filename, bool input_table):
@@ -1011,11 +1040,11 @@ cdef class SymbolTable(_MutableSymbolTable):
 
     See also: `SymbolTable.read`, `SymbolTable.read_text`.
     """
-    cdef fst.SymbolTable *tsyms = fst.FstReadSymbols(tostring(filename),
-                                                     input_table)
-    if tsyms == NULL:
+    cdef unique_ptr[fst.SymbolTable] syms
+    syms.reset(fst.FstReadSymbols(tostring(filename), input_table))
+    if syms.get() == NULL:
       raise FstIOError("Read failed: {!r}".format(filename))
-    return _init_SymbolTable(tsyms)
+    return _init_SymbolTable(syms.release())
 
 
 cdef _EncodeMapperSymbolTable _init_EncodeMapperSymbolTable(
@@ -1050,6 +1079,16 @@ cdef SymbolTable _init_SymbolTable(fst.SymbolTable *table):
   return result
 
 
+cpdef SymbolTable _read_SymbolTable_from_string(state):
+  cdef stringstream sstrm
+  sstrm << tostring(state)
+  cdef unique_ptr[fst.SymbolTable] syms
+  syms.reset(fst.SymbolTable.ReadStream(sstrm, b"<pywrapfst>"))
+  if syms.get() == NULL:
+    raise FstIOError("Read failed")
+  return _init_SymbolTable(syms.release())
+
+
 # Constructive SymbolTable operations.
 
 
@@ -1349,6 +1388,28 @@ cdef class _Fst(object):
   """
 
   # IPython notebook magic to produce an SVG of the FST.
+
+  # Google-only...
+  @staticmethod
+  cdef string _server_render_svg(const string &dot):
+    # Creates request.
+    request = graphviz_server_pb2.RenderRequest()
+    request.graph.dot = dot
+    request.return_bytes = True
+    # Makes request and returns SVG rendering.
+    response = stubby.Call("blade:graphviz-server",
+                           "RenderServer.Render",
+                           request)
+    return response.rendered_graph.rendered_bytes
+  # ...Google-only.
+
+  @staticmethod
+  cdef string _local_render_svg(const string &dot):
+    proc = subprocess.Popen(("dot", "-Tsvg"),
+                            stdin=subprocess.PIPE,
+                            stdout=subprocess.PIPE)
+    return proc.communicate(dot.encode("utf8"))[0]
+
   def _repr_svg_(self):
     """IPython notebook magic to produce an SVG of the FST using GraphViz.
 
@@ -1356,46 +1417,41 @@ cdef class _Fst(object):
     publication-quality graphs should instead use the method `draw`, which
     exposes additional parameters.
 
-    Raises:
-      OSError: Cannot locate the `dot` executable.
-      subprocess.CalledProcessError: `dot` returned non-zero exit code.
-
     See also: `draw`, `text`.
     """
-    # Quickly throws OSError if the dot executable i s not found.
-    proc = subprocess.Popen(["dot", "-Tsvg"],
-                            stdin=subprocess.PIPE,
-                            stdout=subprocess.PIPE,
-                            stderr=subprocess.PIPE)
     cdef stringstream sstrm
+    cdef bool acceptor = (self._fst.get().Properties(fst.kAcceptor, True) ==
+                          fst.kAcceptor)
     fst.DrawFst(deref(self._fst), self._fst.get().InputSymbols(),
-                self._fst.get().OutputSymbols(), NULL,
-                self._fst.get().Properties(fst.kAcceptor, True) ==
-                fst.kAcceptor,
+                self._fst.get().OutputSymbols(), NULL, acceptor,
                 b"", 8.5, 11, True, False, 0.4, 0.25, 14, 5, b"g", False,
-                addr(sstrm), b"_repr_svg")
-    # The stream gets decoded automatically so we have to re-encode it to pass
-    # it to the process.
-    (sout, serr) = proc.communicate(sstrm.str().encode("utf8"))
-    if proc.returncode != 0:  # Just to be explicit.
-      raise subprocess.CalledProcessError(proc.returncode, self._DOT_TSVG)
-    return sout.decode("utf8")
-
-  def __repr__(self):
-    return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+                addr(sstrm), b"<pywrapfst>")
+    # Google-only...
+    try:
+      return _Fst._server_render_svg(sstrm.str())
+    except Exception as e:
+      frontend.DisplayToast("GraphViz server request failed: " + str(e))
+    # ...Google-only.
+    try:
+      return _Fst._local_render_svg(sstrm.str())
+    except Exception as e:
+      logging.warning("Dot rendering failed: " + str(e))
 
   def __init__(self):
     raise FstDeletedConstructorError(
         "Cannot construct {}".format(self.__class__.__name__))
 
-  def __str__(self):
-    return self.text()
-
   # Registers the class for pickling; must be repeated in any subclass which
   # can't be derived by _init_XFst.
 
   def __reduce__(self):
-    return (_read_from_string, (self.write_to_string(),))
+    return (_read_Fst_from_string, (self.write_to_string(),))
+
+  def __repr__(self):
+    return "<{} Fst at 0x{:x}>".format(self.fst_type(), id(self))
+
+  def __str__(self):
+    return self.text()
 
   cpdef string arc_type(self):
     """
@@ -1512,6 +1568,8 @@ cdef class _Fst(object):
     """
     cdef Weight weight = Weight.__new__(Weight)
     weight._weight.reset(new fst.WeightClass(self._fst.get().Final(state)))
+    if weight.to_string() == b"BadNumber":
+      raise FstIndexError("State index out of range")
     return weight
 
   cpdef string fst_type(self):
@@ -1686,7 +1744,7 @@ cdef class _Fst(object):
     if ssymbols is not None:
       ssymbols_ptr = ssymbols._table
     cdef stringstream sstrm
-    fst.PrintFst(deref(self._fst), sstrm, "<pywrapfst>",
+    fst.PrintFst(deref(self._fst), sstrm, b"<pywrapfst>",
         self._fst.get().InputSymbols() if isymbols is None
         else isymbols._table,
         self._fst.get().OutputSymbols() if osymbols is None
@@ -1740,7 +1798,7 @@ cdef class _Fst(object):
     Serializes FST to a string.
 
     Returns:
-      A string.
+      A bytestring.
 
     Raises:
       FstIOError: Write to string failed.
@@ -1748,7 +1806,7 @@ cdef class _Fst(object):
     See also: `read_from_string`.
     """
     cdef stringstream sstrm
-    if not self._fst.get().Write(sstrm, "write_to_string"):
+    if not self._fst.get().Write(sstrm, b"<pywrapfst>"):
       raise FstIOError("Write to string failed")
     return sstrm.str()
 
@@ -1840,8 +1898,6 @@ cdef class _MutableFst(_Fst):
 
     Raises:
       FstArgError: Unknown sort type.
-
-    See also: `topsort`.
     """
     self._arcsort(sort_type)
     return self
@@ -2100,10 +2156,10 @@ cdef class _MutableFst(_Fst):
 
     Returns the FST's (mutable) input symbol table, or None if none is present.
     """
-    cdef fst.SymbolTable *tst = self._mfst.get().MutableInputSymbols()
-    if tst == NULL:
+    cdef fst.SymbolTable *syms = self._mfst.get().MutableInputSymbols()
+    if syms == NULL:
       return
-    return _init_MutableFstSymbolTable(tst, self._mfst)
+    return _init_MutableFstSymbolTable(syms, self._mfst)
 
   def mutable_output_symbols(self):
     """
@@ -2111,10 +2167,10 @@ cdef class _MutableFst(_Fst):
 
     Returns the FST's (mutable) output symbol table, or None if none is present.
     """
-    cdef fst.SymbolTable *tst = self._mfst.get().MutableOutputSymbols()
-    if tst == NULL:
+    cdef fst.SymbolTable *syms = self._mfst.get().MutableOutputSymbols()
+    if syms == NULL:
       return
-    return _init_MutableFstSymbolTable(tst, self._mfst)
+    return _init_MutableFstSymbolTable(syms, self._mfst)
 
   cpdef int64 num_states(self):
     """
@@ -2618,8 +2674,6 @@ cdef class _MutableFst(_Fst):
 
     Returns:
        self.
-
-    See also: `arcsort`.
     """
     self._topsort()
     return self
@@ -2671,7 +2725,7 @@ cdef class _MutableFst(_Fst):
 
 
 cdef _Fst _init_Fst(FstClass_ptr tfst):
-  if tfst.Properties(fst.kError, True):
+  if tfst.Properties(fst.kError, True) == fst.kError:
     raise FstOpError("Operation failed")
   cdef _Fst ofst = _Fst.__new__(_Fst)
   ofst._fst.reset(tfst)
@@ -2679,7 +2733,7 @@ cdef _Fst _init_Fst(FstClass_ptr tfst):
 
 
 cdef _MutableFst _init_MutableFst(MutableFstClass_ptr tfst):
-  if tfst.Properties(fst.kError, True):
+  if tfst.Properties(fst.kError, True) == fst.kError:
     raise FstOpError("Operation failed")
   cdef _MutableFst ofst = _MutableFst.__new__(_MutableFst)
   ofst._fst.reset(tfst)
@@ -2689,7 +2743,7 @@ cdef _MutableFst _init_MutableFst(MutableFstClass_ptr tfst):
 
 
 cdef _Fst _init_XFst(FstClass_ptr tfst):
-  if tfst.Properties(fst.kMutable, True):
+  if tfst.Properties(fst.kMutable, True) == fst.kMutable:
     return _init_MutableFst(static_cast[MutableFstClass_ptr](tfst))
   else:
     return _init_Fst(tfst)
@@ -2711,13 +2765,13 @@ cpdef _Fst _read(filename):
   return _init_XFst(tfst.release())
 
 
-cpdef _Fst _read_from_string(state):
+cpdef _Fst _read_Fst_from_string(state):
   cdef stringstream sstrm
   sstrm << tostring(state)
   cdef unique_ptr[fst.FstClass] tfst
-  tfst.reset(fst.FstClass.ReadFromStream(sstrm, "<pywrapfst>"))
+  tfst.reset(fst.FstClass.ReadStream(sstrm, b"<pywrapfst>"))
   if tfst.get() == NULL:
-    raise FstIOError("Read failed: <string>")
+    raise FstIOError("Read failed")
   return _init_XFst(tfst.release())
 
 
@@ -2778,7 +2832,7 @@ class Fst(object):
 
      See also: `write_to_string`.
      """
-     return _read_from_string(state)
+     return _read_Fst_from_string(state)
 
 
 ## FST constants.
@@ -2786,9 +2840,7 @@ class Fst(object):
 
 NO_LABEL = fst.kNoLabel
 NO_STATE_ID = fst.kNoStateId
-# TODO(kbg): Figure out how to access static class variables so I don't have
-# to do it this way.
-NO_SYMBOL = kNoSymbol
+NO_SYMBOL = fst.kNoSymbol
 
 
 ## FST properties.
@@ -3256,7 +3308,7 @@ cpdef _Fst arcmap(_Fst ifst,
                   double power=1.,
                   weight=None):
   """
-  arcmap(ifst, delta=0.0009765625, map_type="identity", weight=None)
+  arcmap(ifst, delta=0.0009765625, map_type="identity", power=1., weight=None)
 
   Constructively applies a transform to all arcs and final states.
 
@@ -3273,7 +3325,7 @@ cpdef _Fst arcmap(_Fst ifst,
     * power: raises all weights to an integral power.
     * rmweight: replaces all non-Zero weights with 1.
     * superfinal: redirects final states to a new superfinal state.
-    * times: right-multiplies a constant to all weights.
+    * times: right-multiplies a constant by all weights.
     * to_log: converts weights to the log semiring.
     * to_log64: converts weights to the log64 semiring.
     * to_standard: converts weights to the tropical ("standard") semiring.
@@ -3774,7 +3826,7 @@ cpdef _MutableFst randgen(_Fst ifst,
                           bool remove_total_weight=False):
   """
   randgen(ifst, npath=1, seed=0, select="uniform", max_length=2147483647,
-          weight=False, remove_total_weight=False)
+          weighted=False, remove_total_weight=False)
 
   Randomly generate successful paths in an FST.
 
@@ -4163,7 +4215,7 @@ cdef class Compiler(object):
     """
     cdef unique_ptr[fst.FstClass] tfst
     tfst.reset(fst.CompileFstInternal(deref(self._sstrm),
-        "<pywrapfst>", self._fst_type, self._arc_type, self._isymbols,
+        b"<pywrapfst>", self._fst_type, self._arc_type, self._isymbols,
         self._osymbols, self._ssymbols, self._acceptor, self._keep_isymbols,
         self._keep_osymbols, self._keep_state_numbering,
         self._allow_negative_labels))
@@ -4188,7 +4240,10 @@ cdef class Compiler(object):
     Args:
       expression: A string expression to add to compiler string buffer.
     """
-    deref(self._sstrm) << tostring(expression)
+    cdef string line = tostring(expression)
+    if not line.empty() and line.back() != b'\n':
+      line.append(b'\n')
+    deref(self._sstrm) << line
 
 
 ## FarReader and FarWriter.
@@ -4460,18 +4515,5 @@ cdef class FarWriter(object):
   def __setitem__(self, key, _Fst fst):
     self.add(key, fst)
 
-
-## Cleanup operations for module entrance and exit.
-
-
-# Masks fst_error_fatal flags while this module is running, returning to the
-# previous state upon module exit.
-
-
-cdef bool _fst_error_fatal_old = fst.FLAGS_fst_error_fatal
+# Masks fst_error_fatal in-module.
 fst.FLAGS_fst_error_fatal = False
-
-
-@atexit.register
-def _reset_fst_error_fatal():
-  fst.FLAGS_fst_error_fatal = _fst_error_fatal_old
index 8720196..6c8aaf9 100644 (file)
@@ -16,7 +16,7 @@ libfst_LTLIBRARIES = phi-fst.la rho-fst.la sigma-fst.la
 lib_LTLIBRARIES = libfstspecial.la
 
 libfstspecial_la_SOURCES = phi-fst.cc rho-fst.cc sigma-fst.cc
-libfstspecial_la_LDFLAGS = -version-info 13:0:0 -lm $(DL_LIBS)
+libfstspecial_la_LDFLAGS = -version-info 14:0:0 -lm $(DL_LIBS)
 libfstspecial_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 
 phi_fst_la_SOURCES = phi-fst.cc
index 5c7c6a8..b44ecc3 100644 (file)
@@ -389,7 +389,7 @@ AM_CPPFLAGS = -I$(srcdir)/../../include -I$(srcdir)/../../bin $(ICU_CPPFLAGS)
 libfst_LTLIBRARIES = phi-fst.la rho-fst.la sigma-fst.la
 lib_LTLIBRARIES = libfstspecial.la
 libfstspecial_la_SOURCES = phi-fst.cc rho-fst.cc sigma-fst.cc
-libfstspecial_la_LDFLAGS = -version-info 13:0:0 -lm $(DL_LIBS)
+libfstspecial_la_LDFLAGS = -version-info 14:0:0 -lm $(DL_LIBS)
 libfstspecial_la_LIBADD = ../../lib/libfst.la -lm $(DL_LIBS)
 phi_fst_la_SOURCES = phi-fst.cc
 phi_fst_la_LDFLAGS = -module
index ec0d8fd..caf6d30 100644 (file)
@@ -141,7 +141,7 @@ void ArcMap(MutableFst<A> *fst, C *mapper) {
               fst->SetFinal(superfinal, Weight::One());
             }
             final_arc.nextstate = superfinal;
-            fst->AddArc(state, final_arc);
+            fst->AddArc(state, std::move(final_arc));
             fst->SetFinal(state, Weight::Zero());
           } else {
             fst->SetFinal(state, final_arc.weight);
@@ -201,7 +201,7 @@ void ArcMap(const Fst<A> &ifst, MutableFst<B> *ofst, C *mapper) {
   const auto final_action = mapper->FinalAction();
   if (ifst.Properties(kExpanded, false)) {
     ofst->ReserveStates(
-        CountStates(ifst) + final_action == MAP_NO_SUPERFINAL ? 0 : 1);
+        CountStates(ifst) + (final_action == MAP_NO_SUPERFINAL ? 0 : 1));
   }
   // Adds all states.
   for (StateIterator<Fst<A>> siter(ifst); !siter.Done(); siter.Next()) {
@@ -215,7 +215,8 @@ void ArcMap(const Fst<A> &ifst, MutableFst<B> *ofst, C *mapper) {
   for (StateIterator<Fst<A>> siter(ifst); !siter.Done(); siter.Next()) {
     StateId s = siter.Value();
     if (s == ifst.Start()) ofst->SetStart(s);
-    ofst->ReserveArcs(s, ifst.NumArcs(s));
+    ofst->ReserveArcs(
+        s, ifst.NumArcs(s) + (final_action != MAP_NO_SUPERFINAL ? 1 : 0));
     for (ArcIterator<Fst<A>> aiter(ifst, s); !aiter.Done(); aiter.Next()) {
       ofst->AddArc(s, (*mapper)(aiter.Value()));
     }
@@ -239,7 +240,7 @@ void ArcMap(const Fst<A> &ifst, MutableFst<B> *ofst, C *mapper) {
             ofst->SetFinal(superfinal, B::Weight::One());
           }
           final_arc.nextstate = superfinal;
-          ofst->AddArc(s, final_arc);
+          ofst->AddArc(s, std::move(final_arc));
           ofst->SetFinal(s, B::Weight::Zero());
         } else {
           ofst->SetFinal(s, final_arc.weight);
@@ -296,10 +297,11 @@ class ArcMapFstImpl : public CacheImpl<B> {
   using FstImpl<B>::SetInputSymbols;
   using FstImpl<B>::SetOutputSymbols;
 
-  using CacheImpl<B>::PushArc;
+  using CacheImpl<B>::EmplaceArc;
   using CacheImpl<B>::HasArcs;
   using CacheImpl<B>::HasFinal;
   using CacheImpl<B>::HasStart;
+  using CacheImpl<B>::PushArc;
   using CacheImpl<B>::SetArcs;
   using CacheImpl<B>::SetFinal;
   using CacheImpl<B>::SetStart;
@@ -424,8 +426,7 @@ class ArcMapFstImpl : public CacheImpl<B> {
          aiter.Next()) {
       auto aarc = aiter.Value();
       aarc.nextstate = FindOState(aarc.nextstate);
-      const auto &barc = (*mapper_)(aarc);
-      PushArc(s, barc);
+      PushArc(s, (*mapper_)(aarc));
     }
 
     // Check for superfinal arcs.
@@ -440,7 +441,7 @@ class ArcMapFstImpl : public CacheImpl<B> {
           if (final_arc.ilabel != 0 || final_arc.olabel != 0) {
             if (superfinal_ == kNoStateId) superfinal_ = nstates_++;
             final_arc.nextstate = superfinal_;
-            PushArc(s, final_arc);
+            PushArc(s, std::move(final_arc));
           }
           break;
         }
@@ -449,8 +450,8 @@ class ArcMapFstImpl : public CacheImpl<B> {
               (*mapper_)(A(0, 0, fst_->Final(FindIState(s)), kNoStateId));
           if (final_arc.ilabel != 0 || final_arc.olabel != 0 ||
               final_arc.weight != B::Weight::Zero()) {
-            PushArc(s, B(final_arc.ilabel, final_arc.olabel, final_arc.weight,
-                         superfinal_));
+            EmplaceArc(s, final_arc.ilabel, final_arc.olabel, final_arc.weight,
+                       superfinal_);
           }
           break;
         }
@@ -644,7 +645,7 @@ class IdentityArcMapper {
   using FromArc = A;
   using ToArc = A;
 
-  ToArc operator()(const FromArc &arc) const { return arc; }
+  constexpr ToArc operator()(const FromArc &arc) const { return arc; }
 
   constexpr MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; }
 
@@ -656,7 +657,7 @@ class IdentityArcMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const { return props; }
+  constexpr uint64 Properties(uint64 props) const { return props; }
 };
 
 // Mapper that converts all input symbols to epsilon.
@@ -666,7 +667,7 @@ class InputEpsilonMapper {
   using FromArc = A;
   using ToArc = A;
 
-  ToArc operator()(const FromArc &arc) const {
+  constexpr ToArc operator()(const FromArc &arc) const {
     return ToArc(0, arc.olabel, arc.weight, arc.nextstate);
   }
 
@@ -680,7 +681,7 @@ class InputEpsilonMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return (props & kSetArcProperties) | kIEpsilons;
   }
 };
@@ -692,7 +693,7 @@ class OutputEpsilonMapper {
   using FromArc = A;
   using ToArc = A;
 
-  ToArc operator()(const FromArc &arc) const {
+  constexpr ToArc operator()(const FromArc &arc) const {
     return ToArc(arc.ilabel, 0, arc.weight, arc.nextstate);
   }
 
@@ -706,7 +707,7 @@ class OutputEpsilonMapper {
     return MAP_CLEAR_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return (props & kSetArcProperties) | kOEpsilons;
   }
 };
@@ -773,10 +774,10 @@ class WeightConvertMapper {
   using FromWeight = typename FromArc::Weight;
   using ToWeight = typename ToArc::Weight;
 
-  explicit WeightConvertMapper(const Converter &c = Converter())
+  constexpr explicit WeightConvertMapper(const Converter &c = Converter())
       : convert_weight_(c) {}
 
-  ToArc operator()(const FromArc &arc) const {
+  constexpr ToArc operator()(const FromArc &arc) const {
     return ToArc(arc.ilabel, arc.olabel, convert_weight_(arc.weight),
                  arc.nextstate);
   }
@@ -791,10 +792,10 @@ class WeightConvertMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const { return props; }
+  constexpr uint64 Properties(uint64 props) const { return props; }
 
  private:
-  Converter convert_weight_;
+  const Converter convert_weight_;
 };
 
 // Non-precision-changing weight conversions; consider using more efficient
@@ -1058,7 +1059,7 @@ class PlusMapper {
   using ToArc = A;
   using Weight = typename FromArc::Weight;
 
-  explicit PlusMapper(Weight weight) : weight_(std::move(weight)) {}
+  constexpr explicit PlusMapper(Weight weight) : weight_(std::move(weight)) {}
 
   ToArc operator()(const FromArc &arc) const {
     if (arc.weight == Weight::Zero()) return arc;
@@ -1076,7 +1077,7 @@ class PlusMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return props & kWeightInvariantProperties;
   }
 
@@ -1092,7 +1093,7 @@ class TimesMapper {
   using ToArc = A;
   using Weight = typename FromArc::Weight;
 
-  explicit TimesMapper(Weight weight) : weight_(std::move(weight)) {}
+  constexpr explicit TimesMapper(Weight weight) : weight_(std::move(weight)) {}
 
   ToArc operator()(const FromArc &arc) const {
     if (arc.weight == Weight::Zero()) return arc;
@@ -1110,7 +1111,7 @@ class TimesMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return props & kWeightInvariantProperties;
   }
 
@@ -1147,7 +1148,7 @@ class PowerMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return props & kWeightInvariantProperties;
   }
 
@@ -1179,7 +1180,7 @@ class InvertWeightMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return props & kWeightInvariantProperties;
   }
 };
@@ -1210,7 +1211,7 @@ class RmWeightMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return (props & kWeightInvariantProperties) | kUnweighted;
   }
 };
@@ -1243,7 +1244,7 @@ class QuantizeMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return props & kWeightInvariantProperties;
   }
 
@@ -1264,7 +1265,7 @@ class ReverseWeightMapper {
   using FromArc = A;
   using ToArc = B;
 
-  ToArc operator()(const FromArc &arc) const {
+  constexpr ToArc operator()(const FromArc &arc) const {
     return ToArc(arc.ilabel, arc.olabel, arc.weight.Reverse(), arc.nextstate);
   }
 
@@ -1278,7 +1279,7 @@ class ReverseWeightMapper {
     return MAP_COPY_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const { return props; }
+  constexpr uint64 Properties(uint64 props) const { return props; }
 };
 
 }  // namespace fst
index 7bd0c47..5fd4f95 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <climits>
 #include <string>
+#include <type_traits>
 #include <utility>
 
 
@@ -35,12 +36,13 @@ struct ArcTpl {
   Weight weight;
   StateId nextstate;
 
-  ArcTpl() {}
+  ArcTpl() noexcept(std::is_nothrow_default_constructible<Weight>::value) {}
 
-  ArcTpl(Label ilabel, Label olabel, Weight weight, StateId nextstate)
+  template <class T>
+  ArcTpl(Label ilabel, Label olabel, T &&weight, StateId nextstate)
       : ilabel(ilabel),
         olabel(olabel),
-        weight(std::move(weight)),
+        weight(std::forward<T>(weight)),
         nextstate(nextstate) {}
 
   static const string &Type() {
@@ -72,10 +74,11 @@ struct StringArc {
 
   StringArc() = default;
 
-  StringArc(Label ilabel, Label olabel, Weight weight, StateId nextstate)
+  template <class W>
+  StringArc(Label ilabel, Label olabel, W &&weight, StateId nextstate)
       : ilabel(ilabel),
         olabel(olabel),
-        weight(std::move(weight)),
+        weight(std::forward<W>(weight)),
         nextstate(nextstate) {}
 
   static const string &Type() {
@@ -104,10 +107,11 @@ struct GallicArc {
 
   GallicArc() = default;
 
-  GallicArc(Label ilabel, Label olabel, Weight weight, StateId nextstate)
+  template <class W>
+  GallicArc(Label ilabel, Label olabel, W &&weight, StateId nextstate)
       : ilabel(ilabel),
         olabel(olabel),
-        weight(std::move(weight)),
+        weight(std::forward<W>(weight)),
         nextstate(nextstate) {}
 
   explicit GallicArc(const Arc &arc)
@@ -146,10 +150,11 @@ struct ReverseArc {
 
   ReverseArc() = default;
 
-  ReverseArc(Label ilabel, Label olabel, Weight weight, StateId nextstate)
+  template <class W>
+  ReverseArc(Label ilabel, Label olabel, W &&weight, StateId nextstate)
       : ilabel(ilabel),
         olabel(olabel),
-        weight(std::move(weight)),
+        weight(std::forward<W>(weight)),
         nextstate(nextstate) {}
 
   static const string &Type() {
@@ -172,10 +177,11 @@ struct LexicographicArc {
 
   LexicographicArc() = default;
 
-  LexicographicArc(Label ilabel, Label olabel, Weight weight, StateId nextstate)
+  template <class W>
+  LexicographicArc(Label ilabel, Label olabel, W &&weight, StateId nextstate)
       : ilabel(ilabel),
         olabel(olabel),
-        weight(std::move(weight)),
+        weight(std::forward<W>(weight)),
         nextstate(nextstate) {}
 
   static const string &Type() {
@@ -198,10 +204,11 @@ struct ProductArc {
 
   ProductArc() = default;
 
-  ProductArc(Label ilabel, Label olabel, Weight weight, StateId nextstate)
+  template <class W>
+  ProductArc(Label ilabel, Label olabel, W &&weight, StateId nextstate)
       : ilabel(ilabel),
         olabel(olabel),
-        weight(std::move(weight)),
+        weight(std::forward<W>(weight)),
         nextstate(nextstate) {}
 
   static const string &Type() {
@@ -227,10 +234,11 @@ struct PowerArc {
 
   PowerArc() = default;
 
-  PowerArc(Label ilabel, Label olabel, Weight weight, StateId nextstate)
+  template <class W>
+  PowerArc(Label ilabel, Label olabel, W &&weight, StateId nextstate)
       : ilabel(ilabel),
         olabel(olabel),
-        weight(std::move(weight)),
+        weight(std::forward<W>(weight)),
         nextstate(nextstate) {}
 
   static const string &Type() {
@@ -256,10 +264,11 @@ struct SparsePowerArc {
 
   SparsePowerArc() = default;
 
-  SparsePowerArc(Label ilabel, Label olabel, Weight weight, StateId nextstate)
+  template <class W>
+  SparsePowerArc(Label ilabel, Label olabel, W &&weight, StateId nextstate)
       : ilabel(ilabel),
         olabel(olabel),
-        weight(std::move(weight)),
+        weight(std::forward<W>(weight)),
         nextstate(nextstate) {}
 
   static const string &Type() {
@@ -292,10 +301,11 @@ struct ExpectationArc {
 
   ExpectationArc() = default;
 
-  ExpectationArc(Label ilabel, Label olabel, Weight weight, StateId nextstate)
+  template <class W>
+  ExpectationArc(Label ilabel, Label olabel, W &&weight, StateId nextstate)
       : ilabel(ilabel),
         olabel(olabel),
-        weight(std::move(weight)),
+        weight(std::forward<W>(weight)),
         nextstate(nextstate) {}
 
   static const string &Type() {
index b159757..b5ab50e 100644 (file)
@@ -26,7 +26,7 @@ class ArcSortMapper {
   using StateId = typename Arc::StateId;
   using Weight = typename Arc::Weight;
 
-  ArcSortMapper(const Fst<Arc> &fst, const Compare &comp)
+  constexpr ArcSortMapper(const Fst<Arc> &fst, const Compare &comp)
       : fst_(fst), comp_(comp), i_(0) {}
 
   // Allows updating Fst argument; pass only if changed.
@@ -169,13 +169,13 @@ class ArcIterator<ArcSortFst<Arc, Compare>>
 template <class Arc>
 class ILabelCompare {
  public:
-  ILabelCompare() {}
+  constexpr ILabelCompare() {}
 
-  bool operator()(const Arc &arc1, const Arc &arc2) const {
+  constexpr bool operator()(const Arc &arc1, const Arc &arc2) const {
     return arc1.ilabel < arc2.ilabel;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return (props & kArcSortProperties) | kILabelSorted |
            (props & kAcceptor ? kOLabelSorted : 0);
   }
@@ -185,13 +185,13 @@ class ILabelCompare {
 template <class Arc>
 class OLabelCompare {
  public:
-  OLabelCompare() {}
+  constexpr OLabelCompare() {}
 
-  bool operator()(const Arc &arc1, const Arc &arc2) const {
+  constexpr bool operator()(const Arc &arc1, const Arc &arc2) const {
     return arc1.olabel < arc2.olabel;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return (props & kArcSortProperties) | kOLabelSorted |
            (props & kAcceptor ? kILabelSorted : 0);
   }
index 3414b1d..9651cfe 100644 (file)
@@ -8,14 +8,16 @@
 #define FST_BI_TABLE_H_
 
 #include <deque>
-#include <memory>
 #include <functional>
+#include <memory>
+#include <type_traits>
 #include <unordered_map>
 #include <unordered_set>
 #include <vector>
 
 #include <fst/log.h>
 #include <fst/memory.h>
+#include <unordered_set>
 
 namespace fst {
 
@@ -110,6 +112,7 @@ struct HashSet : public std::unordered_set<K, H, E, PoolAllocator<K>> {
 // current_entry_. The hash and key equality functions map to entries first. H
 // is the hash function and E is the equality function. If passed to the
 // constructor, ownership is given to this class.
+// TODO(rybach): remove support for (deprecated and unused) HS_DENSE, HS_SPARSE.
 template <class I, class T, class H, class E = std::equal_to<T>,
           HSType HS = HS_FLAT>
 class CompactHashBiTable {
@@ -177,6 +180,10 @@ class CompactHashBiTable {
   }
 
  private:
+  static_assert(std::is_signed<I>::value, "I must be a signed type");
+  // ... otherwise >= kCurrentKey comparisons as used below don't work.
+  // TODO(rybach): (1) remove kEmptyKey, kDeletedKey, (2) don't use >= for key
+  // comparison, (3) allow unsigned key types.
   static constexpr I kCurrentKey = -1;
   static constexpr I kEmptyKey = -2;
   static constexpr I kDeletedKey = -3;
index 45d158f..295b87b 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef FST_CACHE_H_
 #define FST_CACHE_H_
 
+#include <algorithm>
 #include <functional>
 #include <unordered_map>
 using std::unordered_map;
@@ -125,19 +126,30 @@ class CacheState {
   // Adds one arc at a time with all needed book-keeping; use PushArc and
   // SetArcs for a more efficient alternative.
   void AddArc(const Arc &arc) {
+    IncrementNumEpsilons(arc);
     arcs_.push_back(arc);
-    if (arc.ilabel == 0) ++niepsilons_;
-    if (arc.olabel == 0) ++noepsilons_;
+  }
+
+  void AddArc(Arc &&arc) {
+    IncrementNumEpsilons(arc);
+    arcs_.push_back(std::move(arc));
   }
 
   // Adds one arc at a time with delayed book-keeping; finalize with SetArcs().
   void PushArc(const Arc &arc) { arcs_.push_back(arc); }
 
+  void PushArc(Arc &&arc) { arcs_.push_back(std::move(arc)); }
+
+  // Adds one arc at a time with delayed book-keeping; finalize with SetArcs().
+  template <class... T>
+  void EmplaceArc(T &&... ctor_args) {
+    arcs_.emplace_back(std::forward<T>(ctor_args)...);
+  }
+
   // Finalizes arcs book-keeping; call only once.
   void SetArcs() {
     for (const auto &arc : arcs_) {
-      if (arc.ilabel == 0) ++niepsilons_;
-      if (arc.olabel == 0) ++noepsilons_;
+      IncrementNumEpsilons(arc);
     }
   }
 
@@ -145,8 +157,7 @@ class CacheState {
   void SetArc(const Arc &arc, size_t n) {
     if (arcs_[n].ilabel == 0) --niepsilons_;
     if (arcs_[n].olabel == 0) --noepsilons_;
-    if (arc.ilabel == 0) ++niepsilons_;
-    if (arc.olabel == 0) ++noepsilons_;
+    IncrementNumEpsilons(arc);
     arcs_[n] = arc;
   }
 
@@ -194,6 +205,12 @@ class CacheState {
   }
 
  private:
+  // Update the number of epsilons as a result of having added an arc.
+  void IncrementNumEpsilons(const Arc &arc) {
+    if (arc.ilabel == 0) ++niepsilons_;
+    if (arc.olabel == 0) ++noepsilons_;
+  }
+
   Weight final_;                         // Final weight.
   size_t niepsilons_;                    // # of input epsilons.
   size_t noepsilons_;                    // # of output epsilons.
@@ -250,6 +267,9 @@ class CacheState {
 //   // Deletes all cached states.
 //   void Clear();
 //
+//   // Number of cached states.
+//   StateId CountStates();
+//
 //   // Iterates over cached states (in an arbitrary order); only needed if
 //   // opts.gc is true.
 //   bool Done() const;      // End of iteration.
@@ -335,6 +355,11 @@ class VectorCacheStore {
     state_list_.clear();
   }
 
+  StateId CountStates() const {
+    return std::count_if(state_vec_.begin(), state_vec_.end(),
+                         [](const State *s) { return s != nullptr; });
+  }
+
   // Iterates over cached states (in an arbitrary order); only works if GC is
   // enabled (o.w. avoiding state_list_ overhead).
   bool Done() const { return iter_ == state_list_.end(); }
@@ -443,6 +468,8 @@ class HashCacheStore {
     state_map_.clear();
   }
 
+  StateId CountStates() const { return state_map_.size(); }
+
   // Iterates over cached states (in an arbitrary order).
   bool Done() const { return iter_ == state_map_.end(); }
 
@@ -575,6 +602,8 @@ class FirstCacheStore {
     cache_first_state_ = nullptr;
   }
 
+  StateId CountStates() const { return store_.CountStates(); }
+
   // Iterates over cached states (in an arbitrary order). Only needed if GC is
   // enabled.
   bool Done() const { return store_.Done(); }
@@ -684,6 +713,8 @@ class GCCacheStore {
     cache_size_ = 0;
   }
 
+  StateId CountStates() const { return store_.CountStates(); }
+
   // Iterates over cached states (in an arbitrary order); only needed if GC is
   // enabled.
   bool Done() const { return store_.Done(); }
@@ -894,13 +925,27 @@ class CacheBaseImpl : public FstImpl<typename State::Arc> {
 #endif
 
   // Adds a single arc to a state but delays cache book-keeping. SetArcs must
-  // be called when all PushArc calls at a state are complete. Do not mix with
-  // calls to AddArc.
+  // be called when all PushArc and EmplaceArc calls at a state are complete.
+  // Do not mix with calls to AddArc.
   void PushArc(StateId s, const Arc &arc) {
     auto *state = cache_store_->GetMutableState(s);
     state->PushArc(arc);
   }
 
+  void PushArc(StateId s, Arc &&arc) {
+    auto *state = cache_store_->GetMutableState(s);
+    state->PushArc(std::move(arc));
+  }
+
+  // Adds a single arc to a state but delays cache book-keeping. SetArcs must
+  // be called when all PushArc and EmplaceArc calls at a state are complete.
+  // Do not mix with calls to AddArc.
+  template <class... T>
+  void EmplaceArc(StateId s, T &&... ctor_args) {
+    auto *state = cache_store_->GetMutableState(s);
+    state->EmplaceArc(std::forward<T>(ctor_args)...);
+  }
+
   // Marks arcs of a state as cached and does cache book-keeping after all
   // calls to PushArc have been completed. Do not mix with calls to AddArc.
   void SetArcs(StateId s) {
@@ -1268,6 +1313,8 @@ class ExpanderCacheStore {
 
     void AddArc(const Arc &arc) { state->PushArc(arc); }
 
+    void AddArc(Arc &&arc) { state->PushArc(std::move(arc)); }
+
     void SetFinal(Weight weight) { state->SetFinal(std::move(weight)); }
   };
 };
index df91895..85e9336 100644 (file)
@@ -252,9 +252,7 @@ DefaultCompactStore<Element, Unsigned>::DefaultCompactStore(
   for (StateIterator<Fst<Arc>> siter(fst); !siter.Done(); siter.Next()) {
     ++nstates_;
     const auto s = siter.Value();
-    for (ArcIterator<Fst<Arc>> aiter(fst, s); !aiter.Done(); aiter.Next()) {
-      ++narcs_;
-    }
+    narcs_ += fst.NumArcs(s);
     if (fst.Final(s) != Weight::Zero()) ++nfinals;
   }
   if (compactor.Size() == -1) {
index 0303409..d0d1ec9 100644 (file)
@@ -7,6 +7,8 @@
 #define FST_COMPOSE_H_
 
 #include <algorithm>
+#include <memory>
+#include <utility>
 
 #include <fst/log.h>
 
@@ -368,9 +370,9 @@ class ComposeFstImpl
   void AddArc(StateId s, const Arc &arc1, const Arc &arc2,
               const FilterState &f) {
     const StateTuple tuple(arc1.nextstate, arc2.nextstate, f);
-    const Arc oarc(arc1.ilabel, arc2.olabel, Times(arc1.weight, arc2.weight),
-                   state_table_->FindState(tuple));
-    CacheImpl::PushArc(s, oarc);
+    CacheImpl::EmplaceArc(
+        s, arc1.ilabel, arc2.olabel, Times(arc1.weight, arc2.weight),
+        state_table_->FindState(tuple));
   }
 
   StateId ComputeStart() override {
index 8b1ddaf..9a10fba 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef FST_CONNECT_H_
 #define FST_CONNECT_H_
 
+#include <algorithm>
+#include <memory>
 #include <vector>
 
 #include <fst/dfs-visit.h>
@@ -289,20 +291,26 @@ void Condense(const Fst<Arc> &ifst, MutableFst<Arc> *ofst,
   uint64 props = 0;
   SccVisitor<Arc> scc_visitor(scc, nullptr, nullptr, &props);
   DfsVisit(ifst, &scc_visitor);
+  const auto iter = std::max_element(scc->cbegin(), scc->cend());
+  if (iter == scc->cend()) return;
+  const StateId num_condensed_states = 1 + *iter;
+  ofst->ReserveStates(num_condensed_states);
+  for (StateId c = 0; c < num_condensed_states; ++c) {
+    ofst->AddState();
+  }
   for (StateId s = 0; s < scc->size(); ++s) {
     const auto c = (*scc)[s];
-    while (c >= ofst->NumStates()) ofst->AddState();
     if (s == ifst.Start()) ofst->SetStart(c);
     const auto weight = ifst.Final(s);
     if (weight != Arc::Weight::Zero())
       ofst->SetFinal(c, Plus(ofst->Final(c), weight));
     for (ArcIterator<Fst<Arc>> aiter(ifst, s); !aiter.Done(); aiter.Next()) {
-      auto arc = aiter.Value();
+      const auto &arc = aiter.Value();
       const auto nextc = (*scc)[arc.nextstate];
       if (nextc != c) {
-        while (nextc >= ofst->NumStates()) ofst->AddState();
-        arc.nextstate = nextc;
-        ofst->AddArc(c, arc);
+        Arc condensed_arc = arc;
+        condensed_arc.nextstate = nextc;
+        ofst->AddArc(c, std::move(condensed_arc));
       }
     }
   }
index 1a2cba6..b646730 100644 (file)
@@ -50,8 +50,8 @@ class ConstFstImpl : public FstImpl<A> {
   ConstFstImpl()
       : states_(nullptr),
         arcs_(nullptr),
-        nstates_(0),
         narcs_(0),
+        nstates_(0),
         start_(kNoStateId) {
     string type = "const";
     if (sizeof(Unsigned) != sizeof(uint32)) {
@@ -123,8 +123,8 @@ class ConstFstImpl : public FstImpl<A> {
   std::unique_ptr<MappedFile> arcs_region_;    // Mapped file for arcs.
   ConstState *states_;                         // States representation.
   Arc *arcs_;                                  // Arcs representation.
-  StateId nstates_;                            // Number of states.
   size_t narcs_;                               // Number of arcs.
+  StateId nstates_;                            // Number of states.
   StateId start_;                              // Initial state.
 
   ConstFstImpl(const ConstFstImpl &) = delete;
@@ -145,7 +145,7 @@ constexpr int ConstFstImpl<Arc, Unsigned>::kMinFileVersion;
 
 template <class Arc, class Unsigned>
 ConstFstImpl<Arc, Unsigned>::ConstFstImpl(const Fst<Arc> &fst)
-    : nstates_(0), narcs_(0) {
+    : narcs_(0), nstates_(0) {
   string type = "const";
   if (sizeof(Unsigned) != sizeof(uint32)) {
     type += std::to_string(CHAR_BIT * sizeof(Unsigned));
@@ -157,10 +157,7 @@ ConstFstImpl<Arc, Unsigned>::ConstFstImpl(const Fst<Arc> &fst)
   // Counts states and arcs.
   for (StateIterator<Fst<Arc>> siter(fst); !siter.Done(); siter.Next()) {
     ++nstates_;
-    for (ArcIterator<Fst<Arc>> aiter(fst, siter.Value()); !aiter.Done();
-         aiter.Next()) {
-      ++narcs_;
-    }
+    narcs_ += fst.NumArcs(siter.Value());
   }
   states_region_.reset(MappedFile::Allocate(nstates_ * sizeof(*states_)));
   arcs_region_.reset(MappedFile::Allocate(narcs_ * sizeof(*arcs_)));
index 6d446cd..8613699 100644 (file)
@@ -11,6 +11,7 @@
 #include <forward_list>
 #include <map>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include <fst/log.h>
@@ -230,14 +231,14 @@ class DefaultDeterminizeFilter {
   // Filters transition, possibly modifying label map. Returns true if arc is
   // added to the label map.
   bool FilterArc(const Arc &arc, const Element &src_element,
-                 const Element &dest_element, LabelMap *label_map) const {
+                 Element &&dest_element, LabelMap *label_map) const {
     // Adds element to unique state tuple for arc label.
     auto &det_arc = (*label_map)[arc.ilabel];
     if (det_arc.label == kNoLabel) {
       det_arc = internal::DeterminizeArc<StateTuple>(arc);
       det_arc.dest_tuple->filter_state = FilterState(0);
     }
-    det_arc.dest_tuple->subset.push_front(dest_element);
+    det_arc.dest_tuple->subset.push_front(std::move(dest_element));
     return true;
   }
 
@@ -588,9 +589,8 @@ class DeterminizeFsaImpl : public DeterminizeFstImplBase<Arc> {
   StateId ComputeStart() override {
     const auto s = GetFst().Start();
     if (s == kNoStateId) return kNoStateId;
-    const Element element(s, Weight::One());
     auto *tuple = new StateTuple;
-    tuple->subset.push_front(element);
+    tuple->subset.emplace_front(s, Weight::One());
     tuple->filter_state = filter_->Start();
     return FindState(tuple);
   }
@@ -638,7 +638,7 @@ class DeterminizeFsaImpl : public DeterminizeFstImplBase<Arc> {
     LabelMap label_map;
     GetLabelMap(s, &label_map);
     for (auto it = label_map.begin(); it != label_map.end(); ++it) {
-      AddArc(s, it->second);
+      AddArc(s, std::move(it->second));
     }
     SetArcs(s);
   }
@@ -657,9 +657,10 @@ class DeterminizeFsaImpl : public DeterminizeFstImplBase<Arc> {
       for (ArcIterator<Fst<Arc>> aiter(GetFst(), src_element.state_id);
            !aiter.Done(); aiter.Next()) {
         const auto &arc = aiter.Value();
-        const Element dest_element(arc.nextstate,
-                                   Times(src_element.weight, arc.weight));
-        filter_->FilterArc(arc, src_element, dest_element, label_map);
+        Element dest_element(arc.nextstate,
+                             Times(src_element.weight, arc.weight));
+        filter_->FilterArc(arc, src_element, std::move(dest_element),
+                           label_map);
       }
     }
     for (auto it = label_map->begin(); it != label_map->end(); ++it) {
@@ -703,10 +704,10 @@ class DeterminizeFsaImpl : public DeterminizeFstImplBase<Arc> {
 
   // Adds an arc from state S to the destination state associated with state
   // tuple in det_arc as created by GetLabelMap.
-  void AddArc(StateId s, const DetArc &det_arc) {
-    const Arc arc(det_arc.label, det_arc.label, det_arc.weight,
-                  FindState(det_arc.dest_tuple));
-    CacheImpl<Arc>::PushArc(s, arc);
+  void AddArc(StateId s, DetArc &&det_arc) {
+    CacheImpl<Arc>::EmplaceArc(
+        s, det_arc.label, det_arc.label, std::move(det_arc.weight),
+        FindState(det_arc.dest_tuple));
   }
 
   float delta_;                         // Quantization delta for weights.
index 6a035c9..ed89c6c 100644 (file)
@@ -21,14 +21,27 @@ constexpr uint32 kEqualCompatSymbols = 0x0008;
 constexpr uint32 kEqualAll =
     kEqualFsts | kEqualFstTypes | kEqualCompatProperties | kEqualCompatSymbols;
 
+class WeightApproxEqual {
+ public:
+  explicit WeightApproxEqual(float delta) : delta_(delta) {}
+
+  template <class Weight>
+  bool operator()(const Weight &w1, const Weight &w2) const {
+    return ApproxEqual(w1, w2, delta_);
+  }
+
+ private:
+  float delta_;
+};
+
 // Tests if two Fsts have the same states and arcs in the same order (when
 // etype & kEqualFst).
 // Also optional checks equality of Fst types (etype & kEqualFstTypes) and
 // compatibility of stored properties (etype & kEqualCompatProperties) and
 // of symbol tables (etype & kEqualCompatSymbols).
-template <class Arc>
-bool Equal(const Fst<Arc> &fst1, const Fst<Arc> &fst2, float delta = kDelta,
-           uint32 etype = kEqualFsts) {
+template <class Arc, class WeightEqual>
+bool Equal(const Fst<Arc> &fst1, const Fst<Arc> &fst2,
+           WeightEqual weight_equal, uint32 etype = kEqualFsts) {
   if ((etype & kEqualFstTypes) && (fst1.Type() != fst2.Type())) {
     VLOG(1) << "Equal: Mismatched FST types (" << fst1.Type() << " != "
             << fst2.Type() << ")";
@@ -72,7 +85,7 @@ bool Equal(const Fst<Arc> &fst1, const Fst<Arc> &fst2, float delta = kDelta,
     }
     const auto &final1 = fst1.Final(s1);
     const auto &final2 = fst2.Final(s2);
-    if (!ApproxEqual(final1, final2, delta)) {
+    if (!weight_equal(final1, final2)) {
       VLOG(1) << "Equal: Mismatched final weights at state " << s1
               << " (" << final1 << " != " << final2 << ")";
       return false;
@@ -96,7 +109,7 @@ bool Equal(const Fst<Arc> &fst1, const Fst<Arc> &fst2, float delta = kDelta,
                 << ", arc " << a << " (" << arc1.olabel << " != "
                 << arc2.olabel << ")";
         return false;
-      } else if (!ApproxEqual(arc1.weight, arc2.weight, delta)) {
+      } else if (!weight_equal(arc1.weight, arc2.weight)) {
         VLOG(1) << "Equal: Mismatched arc weights at state " << s1
                 << ", arc " << a << " (" << arc1.weight << " != "
                 << arc2.weight << ")";
@@ -134,6 +147,23 @@ bool Equal(const Fst<Arc> &fst1, const Fst<Arc> &fst2, float delta = kDelta,
   return true;
 }
 
+template <class Arc>
+bool Equal(const Fst<Arc> &fst1, const Fst<Arc> &fst2,
+           float delta = kDelta, uint32 etype = kEqualFsts) {
+  return Equal(fst1, fst2, WeightApproxEqual(delta), etype);
+}
+
+// Support double deltas without forcing all clients to cast to float.
+// Without this overload, Equal<Arc, WeightEqual=double> will be chosen,
+// since it is a better match than double -> float narrowing, but
+// the instantiation will fail.
+template <class Arc>
+bool Equal(const Fst<Arc> &fst1, const Fst<Arc> &fst2,
+           double delta, uint32 etype = kEqualFsts) {
+  return Equal(fst1, fst2, WeightApproxEqual(static_cast<float>(delta)), etype);
+}
+
+
 }  // namespace fst
 
 #endif  // FST_EQUAL_H_
index 614ecef..2c7d514 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <sys/types.h>
 #include <istream>
+#include <memory>
 #include <string>
 
 #include <fst/log.h>
@@ -115,8 +116,6 @@ class ImplToExpandedFst : public ImplToFst<Impl, FST> {
   using StateId = typename Arc::StateId;
   using Weight = typename Arc::Weight;
 
-  using ImplToFst<Impl, FST>::operator=;
-
   StateId NumStates() const override { return GetImpl()->NumStates(); }
 
  protected:
@@ -125,9 +124,6 @@ class ImplToExpandedFst : public ImplToFst<Impl, FST> {
   explicit ImplToExpandedFst(std::shared_ptr<Impl> impl)
       : ImplToFst<Impl, FST>(impl) {}
 
-  ImplToExpandedFst(const ImplToExpandedFst<Impl, FST> &fst)
-      : ImplToFst<Impl, FST>(fst) {}
-
   ImplToExpandedFst(const ImplToExpandedFst<Impl, FST> &fst, bool safe)
       : ImplToFst<Impl, FST>(fst, safe) {}
 
index e639579..f996cbc 100644 (file)
@@ -49,9 +49,6 @@ class ExpectationWeight : public PairWeight<X1, X2> {
 
   ExpectationWeight() : PairWeight<X1, X2>(Zero()) {}
 
-  ExpectationWeight(const ExpectationWeight &weight)
-      : PairWeight<X1, X2>(weight) {}
-
   explicit ExpectationWeight(const PairWeight<X1, X2> &weight)
       : PairWeight<X1, X2>(weight) {}
 
index 2dbacce..50d7be9 100644 (file)
@@ -79,10 +79,7 @@ class FarReaderClassImpl : public FarReaderImplBase {
 
 class FarReaderClass;
 
-using OpenFarReaderClassArgs1 =
-    WithReturnValue<FarReaderClass *, const string &>;
-
-using OpenFarReaderClassArgs2 =
+using OpenFarReaderClassArgs =
     WithReturnValue<FarReaderClass *, const std::vector<string> &>;
 
 // Untemplated user-facing class holding a templated pimpl.
@@ -125,10 +122,7 @@ class FarReaderClass {
   }
 
   template <class Arc>
-  friend void OpenFarReaderClass(OpenFarReaderClassArgs1 *args);
-
-  template <class Arc>
-  friend void OpenFarReaderClass(OpenFarReaderClassArgs2 *args);
+  friend void OpenFarReaderClass(OpenFarReaderClassArgs *args);
 
   // Defined in the CC.
 
@@ -147,12 +141,7 @@ class FarReaderClass {
 // static method FarReaderClass::Open instead.
 
 template <class Arc>
-void OpenFarReaderClass(OpenFarReaderClassArgs1 *args) {
-  args->retval = new FarReaderClass(new FarReaderClassImpl<Arc>(args->args));
-}
-
-template <class Arc>
-void OpenFarReaderClass(OpenFarReaderClassArgs2 *args) {
+void OpenFarReaderClass(OpenFarReaderClassArgs *args) {
   args->retval = new FarReaderClass(new FarReaderClassImpl<Arc>(args->args));
 }
 
index a9dde87..30e0232 100644 (file)
@@ -196,10 +196,10 @@ class FactorWeightFstImpl : public CacheImpl<Arc> {
   using FstImpl<Arc>::SetInputSymbols;
   using FstImpl<Arc>::SetOutputSymbols;
 
-  using CacheBaseImpl<CacheState<Arc>>::PushArc;
-  using CacheBaseImpl<CacheState<Arc>>::HasStart;
-  using CacheBaseImpl<CacheState<Arc>>::HasFinal;
+  using CacheBaseImpl<CacheState<Arc>>::EmplaceArc;
   using CacheBaseImpl<CacheState<Arc>>::HasArcs;
+  using CacheBaseImpl<CacheState<Arc>>::HasFinal;
+  using CacheBaseImpl<CacheState<Arc>>::HasStart;
   using CacheBaseImpl<CacheState<Arc>>::SetArcs;
   using CacheBaseImpl<CacheState<Arc>>::SetFinal;
   using CacheBaseImpl<CacheState<Arc>>::SetStart;
@@ -335,17 +335,17 @@ class FactorWeightFstImpl : public CacheImpl<Arc> {
       for (ArcIterator<Fst<Arc>> ait(*fst_, element.state); !ait.Done();
            ait.Next()) {
         const auto &arc = ait.Value();
-        const auto weight = Times(element.weight, arc.weight);
+        auto weight = Times(element.weight, arc.weight);
         FactorIterator fiter(weight);
         if (!(mode_ & kFactorArcWeights) || fiter.Done()) {
           const auto dest = FindState(Element(arc.nextstate, Weight::One()));
-          PushArc(s, Arc(arc.ilabel, arc.olabel, weight, dest));
+          EmplaceArc(s, arc.ilabel, arc.olabel, std::move(weight), dest);
         } else {
           for (; !fiter.Done(); fiter.Next()) {
-            const auto &pair = fiter.Value();
+            auto pair = fiter.Value();
             const auto dest =
                 FindState(Element(arc.nextstate, pair.second.Quantize(delta_)));
-            PushArc(s, Arc(arc.ilabel, arc.olabel, pair.first, dest));
+            EmplaceArc(s, arc.ilabel, arc.olabel, std::move(pair.first), dest);
           }
         }
       }
@@ -360,10 +360,10 @@ class FactorWeightFstImpl : public CacheImpl<Arc> {
       auto ilabel = final_ilabel_;
       auto olabel = final_olabel_;
       for (FactorIterator fiter(weight); !fiter.Done(); fiter.Next()) {
-        const auto &pair = fiter.Value();
+        auto pair = fiter.Value();
         const auto dest =
             FindState(Element(kNoStateId, pair.second.Quantize(delta_)));
-        PushArc(s, Arc(ilabel, olabel, pair.first, dest));
+        EmplaceArc(s, ilabel, olabel, std::move(pair.first), dest);
         if (increment_final_ilabel_) ++ilabel;
         if (increment_final_olabel_) ++olabel;
       }
index 4003251..b57ea2c 100644 (file)
@@ -6,12 +6,11 @@
 #ifndef FST_FLOAT_WEIGHT_H_
 #define FST_FLOAT_WEIGHT_H_
 
+#include <algorithm>
 #include <climits>
 #include <cmath>
 #include <cstdlib>
 #include <cstring>
-
-#include <algorithm>
 #include <limits>
 #include <sstream>
 #include <string>
@@ -41,16 +40,16 @@ class FloatWeightTpl {
  public:
   using ValueType = T;
 
-  FloatWeightTpl() {}
+  FloatWeightTpl() noexcept {}
 
-  FloatWeightTpl(T f) : value_(f) {}
+  constexpr FloatWeightTpl(T f) : value_(f) {}  // NOLINT
 
-  FloatWeightTpl(const FloatWeightTpl<T> &weight) : value_(weight.value_) {}
+  // TODO(mjansche): Leave implicit once Android NDK r18 is the default.
+  FloatWeightTpl(const FloatWeightTpl<T> &) = default;
+  FloatWeightTpl(FloatWeightTpl<T> &&) noexcept = default;
 
-  FloatWeightTpl<T> &operator=(const FloatWeightTpl<T> &weight) {
-    value_ = weight.value_;
-    return *this;
-  }
+  FloatWeightTpl<T> &operator=(const FloatWeightTpl<T> &) = default;
+  FloatWeightTpl<T> &operator=(FloatWeightTpl<T> &&) noexcept = default;
 
   std::istream &Read(std::istream &strm) { return ReadType(strm, &value_); }
 
@@ -68,18 +67,17 @@ class FloatWeightTpl {
     return hash;
   }
 
-  const T &Value() const { return value_; }
+  constexpr const T &Value() const { return value_; }
 
  protected:
   void SetValue(const T &f) { value_ = f; }
 
   static constexpr const char *GetPrecisionString() {
-    return sizeof(T) == 4
-               ? ""
-               : sizeof(T) == 1
-                     ? "8"
-                     : sizeof(T) == 2 ? "16"
-                                      : sizeof(T) == 8 ? "64" : "unknown";
+    return sizeof(T) == 4 ? ""
+        : sizeof(T) == 1 ? "8"
+        : sizeof(T) == 2 ? "16"
+        : sizeof(T) == 8 ? "64"
+        : "unknown";
   }
 
  private:
@@ -90,49 +88,57 @@ class FloatWeightTpl {
 using FloatWeight = FloatWeightTpl<float>;
 
 template <class T>
-inline bool operator==(const FloatWeightTpl<T> &w1,
-                       const FloatWeightTpl<T> &w2) {
-  // Volatile qualifier thwarts over-aggressive compiler optimizations that
-  // lead to problems esp. with NaturalLess().
-  volatile T v1 = w1.Value();
-  volatile T v2 = w2.Value();
-  return v1 == v2;
+constexpr bool operator==(const FloatWeightTpl<T> &w1,
+                          const FloatWeightTpl<T> &w2) {
+#if (defined(__i386__) || defined(__x86_64__)) && !defined(__SSE2_MATH__)
+// With i387 instructions, excess precision on a weight in an 80-bit
+// register may cause it to compare unequal to that same weight when
+// stored to memory.  This breaks =='s reflexivity, in turn breaking
+// NaturalLess.
+#error "Please compile with -msse -mfpmath=sse, or equivalent."
+#endif
+  return w1.Value() == w2.Value();
 }
 
 // These seemingly unnecessary overloads are actually needed to make
 // comparisons like FloatWeightTpl<float> == float compile.  If only the
 // templated version exists, the FloatWeightTpl<float>(float) conversion
 // won't be found.
-inline bool operator==(const FloatWeightTpl<float> &w1,
-                       const FloatWeightTpl<float> &w2) {
+constexpr bool operator==(const FloatWeightTpl<float> &w1,
+                          const FloatWeightTpl<float> &w2) {
   return operator==<float>(w1, w2);
 }
 
-inline bool operator==(const FloatWeightTpl<double> &w1,
-                       const FloatWeightTpl<double> &w2) {
+constexpr bool operator==(const FloatWeightTpl<double> &w1,
+                          const FloatWeightTpl<double> &w2) {
   return operator==<double>(w1, w2);
 }
 
 template <class T>
-inline bool operator!=(const FloatWeightTpl<T> &w1,
-                       const FloatWeightTpl<T> &w2) {
+constexpr bool operator!=(const FloatWeightTpl<T> &w1,
+                          const FloatWeightTpl<T> &w2) {
   return !(w1 == w2);
 }
 
-inline bool operator!=(const FloatWeightTpl<float> &w1,
-                       const FloatWeightTpl<float> &w2) {
+constexpr bool operator!=(const FloatWeightTpl<float> &w1,
+                          const FloatWeightTpl<float> &w2) {
   return operator!=<float>(w1, w2);
 }
 
-inline bool operator!=(const FloatWeightTpl<double> &w1,
-                       const FloatWeightTpl<double> &w2) {
+constexpr bool operator!=(const FloatWeightTpl<double> &w1,
+                          const FloatWeightTpl<double> &w2) {
   return operator!=<double>(w1, w2);
 }
 
 template <class T>
-inline bool ApproxEqual(const FloatWeightTpl<T> &w1,
-                        const FloatWeightTpl<T> &w2, float delta = kDelta) {
-  return w1.Value() <= w2.Value() + delta && w2.Value() <= w1.Value() + delta;
+constexpr bool FloatApproxEqual(T w1, T w2, float delta = kDelta) {
+  return w1 <= w2 + delta && w2 <= w1 + delta;
+}
+
+template <class T>
+constexpr bool ApproxEqual(const FloatWeightTpl<T> &w1,
+                           const FloatWeightTpl<T> &w2, float delta = kDelta) {
+  return FloatApproxEqual(w1.Value(), w2.Value(), delta);
 }
 
 template <class T>
@@ -178,26 +184,16 @@ class TropicalWeightTpl : public FloatWeightTpl<T> {
   using ReverseWeight = TropicalWeightTpl<T>;
   using Limits = FloatLimits<T>;
 
-  constexpr TropicalWeightTpl() : FloatWeightTpl<T>() {}
+  TropicalWeightTpl() noexcept : FloatWeightTpl<T>() {}
 
   constexpr TropicalWeightTpl(T f) : FloatWeightTpl<T>(f) {}
 
-  constexpr TropicalWeightTpl(const TropicalWeightTpl<T> &weight)
-      : FloatWeightTpl<T>(weight) {}
+  static constexpr TropicalWeightTpl<T> Zero() { return Limits::PosInfinity(); }
 
-  static const TropicalWeightTpl<T> &Zero() {
-    static const TropicalWeightTpl zero(Limits::PosInfinity());
-    return zero;
-  }
+  static constexpr TropicalWeightTpl<T> One() { return 0; }
 
-  static const TropicalWeightTpl<T> &One() {
-    static const TropicalWeightTpl one(0.0F);
-    return one;
-  }
-
-  static const TropicalWeightTpl<T> &NoWeight() {
-    static const TropicalWeightTpl no_weight(Limits::NumberBad());
-    return no_weight;
+  static constexpr TropicalWeightTpl<T> NoWeight() {
+    return Limits::NumberBad();
   }
 
   static const string &Type() {
@@ -207,9 +203,9 @@ class TropicalWeightTpl : public FloatWeightTpl<T> {
     return *type;
   }
 
-  bool Member() const {
-    // First part fails for IEEE NaN.
-    return Value() == Value() && Value() != Limits::NegInfinity();
+  constexpr bool Member() const {
+    // Fails for IEEE NaN.
+    return Value() > Limits::NegInfinity();
   }
 
   TropicalWeightTpl<T> Quantize(float delta = kDelta) const {
@@ -220,7 +216,7 @@ class TropicalWeightTpl : public FloatWeightTpl<T> {
     }
   }
 
-  TropicalWeightTpl<T> Reverse() const { return *this; }
+  constexpr TropicalWeightTpl<T> Reverse() const { return *this; }
 
   static constexpr uint64 Properties() {
     return kLeftSemiring | kRightSemiring | kCommutative | kPath | kIdempotent;
@@ -230,22 +226,27 @@ class TropicalWeightTpl : public FloatWeightTpl<T> {
 // Single precision tropical weight.
 using TropicalWeight = TropicalWeightTpl<float>;
 
+static_assert(!TropicalWeight::NoWeight().Member(), "NoWeight not member");
+static_assert(TropicalWeight::Zero().Member(), "Zero is member");
+static_assert(TropicalWeight::One().Member(), "One is member");
+static_assert(TropicalWeight::Zero() != TropicalWeight::One(), "Zero != One");
+
 template <class T>
-inline TropicalWeightTpl<T> Plus(const TropicalWeightTpl<T> &w1,
-                                 const TropicalWeightTpl<T> &w2) {
-  if (!w1.Member() || !w2.Member()) return TropicalWeightTpl<T>::NoWeight();
-  return w1.Value() < w2.Value() ? w1 : w2;
+constexpr TropicalWeightTpl<T> Plus(const TropicalWeightTpl<T> &w1,
+                                    const TropicalWeightTpl<T> &w2) {
+  return (!w1.Member() || !w2.Member()) ? TropicalWeightTpl<T>::NoWeight()
+      : w1.Value() < w2.Value() ? w1 : w2;
 }
 
 // See comment at operator==(FloatWeightTpl<float>, FloatWeightTpl<float>)
 // for why these overloads are present.
-inline TropicalWeightTpl<float> Plus(const TropicalWeightTpl<float> &w1,
-                                     const TropicalWeightTpl<float> &w2) {
+constexpr TropicalWeightTpl<float> Plus(const TropicalWeightTpl<float> &w1,
+                                        const TropicalWeightTpl<float> &w2) {
   return Plus<float>(w1, w2);
 }
 
-inline TropicalWeightTpl<double> Plus(const TropicalWeightTpl<double> &w1,
-                                      const TropicalWeightTpl<double> &w2) {
+constexpr TropicalWeightTpl<double> Plus(const TropicalWeightTpl<double> &w1,
+                                         const TropicalWeightTpl<double> &w2) {
   return Plus<double>(w1, w2);
 }
 
@@ -279,17 +280,12 @@ template <class T>
 inline TropicalWeightTpl<T> Divide(const TropicalWeightTpl<T> &w1,
                                    const TropicalWeightTpl<T> &w2,
                                    DivideType typ = DIVIDE_ANY) {
-  using Limits = FloatLimits<T>;
-  if (!w1.Member() || !w2.Member()) return TropicalWeightTpl<T>::NoWeight();
-  const T f1 = w1.Value();
-  const T f2 = w2.Value();
-  if (f2 == Limits::PosInfinity()) {
-    return Limits::NumberBad();
-  } else if (f1 == Limits::PosInfinity()) {
-    return Limits::PosInfinity();
-  } else {
-    return TropicalWeightTpl<T>(f1 - f2);
-  }
+  using Weight = TropicalWeightTpl<T>;
+  if (!w1.Member() || !w2.Member() || w2 == Weight::Zero())
+    return Weight::NoWeight();
+  if (w1 == Weight::Zero())
+    return Weight::Zero();
+  return Weight(w1.Value() - w2.Value());
 }
 
 inline TropicalWeightTpl<float> Divide(const TropicalWeightTpl<float> &w1,
@@ -339,27 +335,15 @@ class LogWeightTpl : public FloatWeightTpl<T> {
   using ReverseWeight = LogWeightTpl;
   using Limits = FloatLimits<T>;
 
-  constexpr LogWeightTpl() : FloatWeightTpl<T>() {}
+  LogWeightTpl() noexcept : FloatWeightTpl<T>() {}
 
   constexpr LogWeightTpl(T f) : FloatWeightTpl<T>(f) {}
 
-  constexpr LogWeightTpl(const LogWeightTpl<T> &weight)
-      : FloatWeightTpl<T>(weight) {}
-
-  static const LogWeightTpl &Zero() {
-    static const LogWeightTpl zero(Limits::PosInfinity());
-    return zero;
-  }
+  static constexpr LogWeightTpl Zero() { return Limits::PosInfinity(); }
 
-  static const LogWeightTpl &One() {
-    static const LogWeightTpl one(0.0F);
-    return one;
-  }
+  static constexpr LogWeightTpl One() { return 0; }
 
-  static const LogWeightTpl &NoWeight() {
-    static const LogWeightTpl no_weight(Limits::NumberBad());
-    return no_weight;
-  }
+  static constexpr LogWeightTpl NoWeight() { return Limits::NumberBad(); }
 
   static const string &Type() {
     static const string *const type =
@@ -367,9 +351,9 @@ class LogWeightTpl : public FloatWeightTpl<T> {
     return *type;
   }
 
-  bool Member() const {
-    // First part fails for IEEE NaN.
-    return Value() == Value() && Value() != Limits::NegInfinity();
+  constexpr bool Member() const {
+    // Fails for IEEE NaN.
+    return Value() > Limits::NegInfinity();
   }
 
   LogWeightTpl<T> Quantize(float delta = kDelta) const {
@@ -380,7 +364,7 @@ class LogWeightTpl : public FloatWeightTpl<T> {
     }
   }
 
-  LogWeightTpl<T> Reverse() const { return *this; }
+  constexpr LogWeightTpl<T> Reverse() const { return *this; }
 
   static constexpr uint64 Properties() {
     return kLeftSemiring | kRightSemiring | kCommutative;
@@ -490,17 +474,12 @@ template <class T>
 inline LogWeightTpl<T> Divide(const LogWeightTpl<T> &w1,
                               const LogWeightTpl<T> &w2,
                               DivideType typ = DIVIDE_ANY) {
-  using Limits = FloatLimits<T>;
-  if (!w1.Member() || !w2.Member()) return LogWeightTpl<T>::NoWeight();
-  const T f1 = w1.Value();
-  const T f2 = w2.Value();
-  if (f2 == Limits::PosInfinity()) {
-    return Limits::NumberBad();
-  } else if (f1 == Limits::PosInfinity()) {
-    return Limits::PosInfinity();
-  } else {
-    return LogWeightTpl<T>(f1 - f2);
-  }
+  using Weight = LogWeightTpl<T>;
+  if (!w1.Member() || !w2.Member() || w2 == Weight::Zero())
+    return Weight::NoWeight();
+  if (w1 == Weight::Zero())
+    return Weight::Zero();
+  return Weight(w1.Value() - w2.Value());
 }
 
 inline LogWeightTpl<float> Divide(const LogWeightTpl<float> &w1,
@@ -587,27 +566,15 @@ class MinMaxWeightTpl : public FloatWeightTpl<T> {
   using ReverseWeight = MinMaxWeightTpl<T>;
   using Limits = FloatLimits<T>;
 
-  MinMaxWeightTpl() : FloatWeightTpl<T>() {}
+  MinMaxWeightTpl() noexcept : FloatWeightTpl<T>() {}
 
-  MinMaxWeightTpl(T f) : FloatWeightTpl<T>(f) {}
+  constexpr MinMaxWeightTpl(T f) : FloatWeightTpl<T>(f) {}  // NOLINT
 
-  MinMaxWeightTpl(const MinMaxWeightTpl<T> &weight)
-      : FloatWeightTpl<T>(weight) {}
+  static constexpr MinMaxWeightTpl Zero() { return Limits::PosInfinity(); }
 
-  static const MinMaxWeightTpl &Zero() {
-    static const MinMaxWeightTpl zero(Limits::PosInfinity());
-    return zero;
-  }
-
-  static const MinMaxWeightTpl &One() {
-    static const MinMaxWeightTpl one(Limits::NegInfinity());
-    return one;
-  }
+  static constexpr MinMaxWeightTpl One() { return Limits::NegInfinity(); }
 
-  static const MinMaxWeightTpl &NoWeight() {
-    static const MinMaxWeightTpl no_weight(Limits::NumberBad());
-    return no_weight;
-  }
+  static constexpr MinMaxWeightTpl NoWeight() { return Limits::NumberBad(); }
 
   static const string &Type() {
     static const string *const type =
@@ -616,7 +583,7 @@ class MinMaxWeightTpl : public FloatWeightTpl<T> {
   }
 
   // Fails for IEEE NaN.
-  bool Member() const { return Value() == Value(); }
+  constexpr bool Member() const { return Value() == Value(); }
 
   MinMaxWeightTpl<T> Quantize(float delta = kDelta) const {
     // If one of infinities, or a NaN.
@@ -628,7 +595,7 @@ class MinMaxWeightTpl : public FloatWeightTpl<T> {
     }
   }
 
-  MinMaxWeightTpl<T> Reverse() const { return *this; }
+  constexpr MinMaxWeightTpl<T> Reverse() const { return *this; }
 
   static constexpr uint64 Properties() {
     return kLeftSemiring | kRightSemiring | kCommutative | kIdempotent | kPath;
@@ -640,93 +607,103 @@ using MinMaxWeight = MinMaxWeightTpl<float>;
 
 // Min.
 template <class T>
-inline MinMaxWeightTpl<T> Plus(const MinMaxWeightTpl<T> &w1,
+constexpr MinMaxWeightTpl<T> Plus(const MinMaxWeightTpl<T> &w1,
                                const MinMaxWeightTpl<T> &w2) {
-  if (!w1.Member() || !w2.Member()) return MinMaxWeightTpl<T>::NoWeight();
-  return w1.Value() < w2.Value() ? w1 : w2;
+  return (!w1.Member() || !w2.Member()) ? MinMaxWeightTpl<T>::NoWeight()
+      : w1.Value() < w2.Value() ? w1 : w2;
 }
 
-inline MinMaxWeightTpl<float> Plus(const MinMaxWeightTpl<float> &w1,
-                                   const MinMaxWeightTpl<float> &w2) {
+constexpr MinMaxWeightTpl<float> Plus(const MinMaxWeightTpl<float> &w1,
+                                      const MinMaxWeightTpl<float> &w2) {
   return Plus<float>(w1, w2);
 }
 
-inline MinMaxWeightTpl<double> Plus(const MinMaxWeightTpl<double> &w1,
-                                    const MinMaxWeightTpl<double> &w2) {
+constexpr MinMaxWeightTpl<double> Plus(const MinMaxWeightTpl<double> &w1,
+                                       const MinMaxWeightTpl<double> &w2) {
   return Plus<double>(w1, w2);
 }
 
 // Max.
 template <class T>
-inline MinMaxWeightTpl<T> Times(const MinMaxWeightTpl<T> &w1,
-                                const MinMaxWeightTpl<T> &w2) {
-  if (!w1.Member() || !w2.Member()) return MinMaxWeightTpl<T>::NoWeight();
-  return w1.Value() >= w2.Value() ? w1 : w2;
+constexpr MinMaxWeightTpl<T> Times(const MinMaxWeightTpl<T> &w1,
+                                   const MinMaxWeightTpl<T> &w2) {
+  return (!w1.Member() || !w2.Member()) ? MinMaxWeightTpl<T>::NoWeight()
+      : w1.Value() >= w2.Value() ? w1 : w2;
 }
 
-inline MinMaxWeightTpl<float> Times(const MinMaxWeightTpl<float> &w1,
-                                    const MinMaxWeightTpl<float> &w2) {
+constexpr MinMaxWeightTpl<float> Times(const MinMaxWeightTpl<float> &w1,
+                                       const MinMaxWeightTpl<float> &w2) {
   return Times<float>(w1, w2);
 }
 
-inline MinMaxWeightTpl<double> Times(const MinMaxWeightTpl<double> &w1,
-                                     const MinMaxWeightTpl<double> &w2) {
+constexpr MinMaxWeightTpl<double> Times(const MinMaxWeightTpl<double> &w1,
+                                        const MinMaxWeightTpl<double> &w2) {
   return Times<double>(w1, w2);
 }
 
 // Defined only for special cases.
 template <class T>
-inline MinMaxWeightTpl<T> Divide(const MinMaxWeightTpl<T> &w1,
-                                 const MinMaxWeightTpl<T> &w2,
-                                 DivideType typ = DIVIDE_ANY) {
-  if (!w1.Member() || !w2.Member()) return MinMaxWeightTpl<T>::NoWeight();
-  // min(w1, x) = w2, w1 >= w2 => min(w1, x) = w2, x = w2.
-  return w1.Value() >= w2.Value() ? w1 : FloatLimits<T>::NumberBad();
+constexpr MinMaxWeightTpl<T> Divide(const MinMaxWeightTpl<T> &w1,
+                                    const MinMaxWeightTpl<T> &w2,
+                                    DivideType typ = DIVIDE_ANY) {
+  return w1.Value() >= w2.Value() ? w1 : MinMaxWeightTpl<T>::NoWeight();
 }
 
-inline MinMaxWeightTpl<float> Divide(const MinMaxWeightTpl<float> &w1,
-                                     const MinMaxWeightTpl<float> &w2,
-                                     DivideType typ = DIVIDE_ANY) {
+constexpr MinMaxWeightTpl<float> Divide(const MinMaxWeightTpl<float> &w1,
+                                        const MinMaxWeightTpl<float> &w2,
+                                        DivideType typ = DIVIDE_ANY) {
   return Divide<float>(w1, w2, typ);
 }
 
-inline MinMaxWeightTpl<double> Divide(const MinMaxWeightTpl<double> &w1,
-                                      const MinMaxWeightTpl<double> &w2,
-                                      DivideType typ = DIVIDE_ANY) {
+constexpr MinMaxWeightTpl<double> Divide(const MinMaxWeightTpl<double> &w1,
+                                         const MinMaxWeightTpl<double> &w2,
+                                         DivideType typ = DIVIDE_ANY) {
   return Divide<double>(w1, w2, typ);
 }
 
 // Converts to tropical.
 template <>
 struct WeightConvert<LogWeight, TropicalWeight> {
-  TropicalWeight operator()(const LogWeight &w) const { return w.Value(); }
+  constexpr TropicalWeight operator()(const LogWeight &w) const {
+    return w.Value();
+  }
 };
 
 template <>
 struct WeightConvert<Log64Weight, TropicalWeight> {
-  TropicalWeight operator()(const Log64Weight &w) const { return w.Value(); }
+  constexpr TropicalWeight operator()(const Log64Weight &w) const {
+    return w.Value();
+  }
 };
 
 // Converts to log.
 template <>
 struct WeightConvert<TropicalWeight, LogWeight> {
-  LogWeight operator()(const TropicalWeight &w) const { return w.Value(); }
+  constexpr LogWeight operator()(const TropicalWeight &w) const {
+    return w.Value();
+  }
 };
 
 template <>
 struct WeightConvert<Log64Weight, LogWeight> {
-  LogWeight operator()(const Log64Weight &w) const { return w.Value(); }
+  constexpr LogWeight operator()(const Log64Weight &w) const {
+    return w.Value();
+  }
 };
 
 // Converts to log64.
 template <>
 struct WeightConvert<TropicalWeight, Log64Weight> {
-  Log64Weight operator()(const TropicalWeight &w) const { return w.Value(); }
+  constexpr Log64Weight operator()(const TropicalWeight &w) const {
+    return w.Value();
+  }
 };
 
 template <>
 struct WeightConvert<LogWeight, Log64Weight> {
-  Log64Weight operator()(const LogWeight &w) const { return w.Value(); }
+  constexpr Log64Weight operator()(const LogWeight &w) const {
+    return w.Value();
+  }
 };
 
 // This function object returns random integers chosen from [0,
index e9182bc..20e6bb3 100644 (file)
@@ -645,8 +645,20 @@ class FstImpl {
         isymbols_(impl.isymbols_ ? impl.isymbols_->Copy() : nullptr),
         osymbols_(impl.osymbols_ ? impl.osymbols_->Copy() : nullptr) {}
 
+  FstImpl(FstImpl<Arc> &&impl) noexcept;
+
   virtual ~FstImpl() {}
 
+  FstImpl &operator=(const FstImpl<Arc> &impl) {
+    properties_ = impl.properties_;
+    type_ = impl.type_;
+    isymbols_ = impl.isymbols_ ? impl.isymbols_->Copy() : nullptr;
+    osymbols_ = impl.osymbols_ ? impl.osymbols_->Copy() : nullptr;
+    return *this;
+  }
+
+  FstImpl &operator=(FstImpl<Arc> &&impl) noexcept;
+
   const string &Type() const { return type_; }
 
   void SetType(const string &type) { type_ = type; }
@@ -790,6 +802,13 @@ class FstImpl {
 };
 
 template <class Arc>
+inline FstImpl<Arc>::FstImpl(FstImpl<Arc> &&) noexcept = default;
+
+template <class Arc>
+inline FstImpl<Arc> &FstImpl<Arc>::operator=(
+    FstImpl<Arc> &&) noexcept = default;
+
+template <class Arc>
 bool FstImpl<Arc>::ReadHeader(std::istream &strm, const FstReadOptions &opts,
                               int min_version, FstHeader *hdr) {
   if (opts.header) {
@@ -852,7 +871,6 @@ class ImplToFst : public FST {
   using Arc = typename Impl::Arc;
   using StateId = typename Arc::StateId;
   using Weight = typename Arc::Weight;
-  using FST::operator=;
 
   StateId Start() const override { return impl_->Start(); }
 
@@ -901,6 +919,28 @@ class ImplToFst : public FST {
     }
   }
 
+  ImplToFst() = delete;
+
+  ImplToFst(const ImplToFst<Impl, FST> &fst) : impl_(fst.impl_) {}
+
+  ImplToFst(ImplToFst<Impl, FST> &&fst) noexcept
+      : impl_(std::move(fst.impl_)) {
+    fst.impl_ = std::make_shared<Impl>();
+  }
+
+  ImplToFst<Impl, FST> &operator=(const ImplToFst<Impl, FST> &fst) {
+    impl_ = fst.impl_;
+    return *this;
+  }
+
+  ImplToFst<Impl, FST> &operator=(ImplToFst<Impl, FST> &&fst) noexcept {
+    if (this != &fst) {
+      impl_ = std::move(fst.impl_);
+      fst.impl_ = std::make_shared<Impl>();
+    }
+    return *this;
+  }
+
   // Returns raw pointers to the shared object.
   const Impl *GetImpl() const { return impl_.get(); }
 
@@ -911,7 +951,7 @@ class ImplToFst : public FST {
 
   bool Unique() const { return impl_.unique(); }
 
-  void SetImpl(std::shared_ptr<Impl> impl) { impl_ = impl; }
+  void SetImpl(std::shared_ptr<Impl> impl) { impl_ = std::move(impl); }
 
  private:
   template <class IFST, class OFST>
index fca6cc2..f3d7f2b 100644 (file)
@@ -398,16 +398,17 @@ class LabelReachable {
         ++indeg[arc.nextstate];  // Finds in-degrees for next step.
       }
       // Redirects final weights to new final state.
-      const auto final_weight = fst_->Final(s);
+      auto final_weight = fst_->Final(s);
       if (final_weight != Weight::Zero()) {
         auto insert_result = label2state_.insert(std::make_pair(kNoLabel, ons));
         if (insert_result.second) {
           indeg.push_back(0);
           ++ons;
         }
-        Arc arc(kNoLabel, kNoLabel, final_weight, label2state_[kNoLabel]);
-        fst_->AddArc(s, arc);
-        ++indeg[arc.nextstate];  // Finds in-degrees for next step.
+        const auto nextstate = label2state_[kNoLabel];
+        fst_->EmplaceArc(s, kNoLabel, kNoLabel, std::move(final_weight),
+                         nextstate);
+        ++indeg[nextstate];  // Finds in-degrees for next step.
         fst_->SetFinal(s, Weight::Zero());
       }
     }
@@ -421,8 +422,7 @@ class LabelReachable {
     fst_->SetStart(start);
     for (StateId s = 0; s < start; ++s) {
       if (indeg[s] == 0) {
-        Arc arc(0, 0, Weight::One(), s);
-        fst_->AddArc(start, arc);
+        fst_->EmplaceArc(start, 0, 0, Weight::One(), s);
       }
     }
   }
index 0471ff8..adb33c2 100644 (file)
@@ -43,6 +43,12 @@ class MappedFile {
   static MappedFile *Map(std::istream *istrm, bool memorymap,
                          const string &source, size_t size);
 
+  // Returns a MappedFile object that contains the contents of the file referred
+  // to by the file descriptor starting from pos with size bytes. If the
+  // memory mapping fails, nullptr is returned. In contrast to Map(), this
+  // factory function does not backoff to allocating and reading.
+  static MappedFile *MapFromFileDescriptor(int fd, int pos, size_t size);
+
   // Creates a MappedFile object with a new[]'ed block of memory of size. The
   // align argument can be used to specify a desired block alignment.
   // This is RECOMMENDED FOR INTERNAL USE ONLY as it may change in future
index 2f23cfc..d9528d6 100644 (file)
@@ -344,22 +344,33 @@ class SortedMatcher : public MatcherBase<typename F::Arc> {
 // Returns true iff match to match_label_. The arc iterator is positioned at the
 // lower bound, that is, the first element greater than or equal to
 // match_label_, or the end if all elements are less than match_label_.
+// If multiple elements are equal to the `match_label_`, returns the rightmost
+// one.
 template <class FST>
 inline bool SortedMatcher<FST>::BinarySearch() {
-  size_t low = 0;
-  size_t high = narcs_;
-  while (low < high) {
-    const size_t mid = low + (high - low) / 2;
+  size_t size = narcs_;
+  if (size == 0) {
+    return false;
+  }
+  size_t high = size - 1;
+  while (size > 1) {
+    const size_t half = size / 2;
+    const size_t mid = high - half;
     aiter_->Seek(mid);
-    if (GetLabel() < match_label_) {
-      low = mid + 1;
-    } else {
+    if (GetLabel() >= match_label_) {
       high = mid;
     }
+    size -= half;
   }
-
-  aiter_->Seek(low);
-  return low < narcs_ && GetLabel() == match_label_;
+  aiter_->Seek(high);
+  const auto label = GetLabel();
+  if (label == match_label_) {
+    return true;
+  }
+  if (label < match_label_) {
+    aiter_->Next();
+  }
+  return false;
 }
 
 // Returns true iff match to match_label_, positioning arc iterator at lower
index 2394784..9f17a22 100644 (file)
@@ -437,7 +437,7 @@ void MergeStates(const Partition<typename Arc::StateId> &partition,
         if (s == state_map[c]) {  // For the first state, just sets destination.
           aiter.SetValue(arc);
         } else {
-          fst->AddArc(state_map[c], arc);
+          fst->AddArc(state_map[c], std::move(arc));
         }
       }
     }
index cf15da9..9031770 100644 (file)
@@ -56,6 +56,10 @@ class MutableFst : public ExpandedFst<A> {
   // Adds an arc to state.
   virtual void AddArc(StateId, const Arc &arc) = 0;
 
+  // Adds an arc (passed by rvalue reference) to state. Allows subclasses
+  // to optionally implement move semantics. Defaults to lvalue overload.
+  virtual void AddArc(StateId state, Arc &&arc) { AddArc(state, arc); }
+
   // Deletes some states, preserving original StateId ordering.
   virtual void DeleteStates(const std::vector<StateId> &) = 0;
 
@@ -301,6 +305,11 @@ class ImplToMutableFst : public ImplToExpandedFst<Impl, FST> {
     GetMutableImpl()->AddArc(s, arc);
   }
 
+  void AddArc(StateId s, Arc &&arc) override {
+    MutateCheck();
+    GetMutableImpl()->AddArc(s, std::move(arc));
+  }
+
   void DeleteStates(const std::vector<StateId> &dstates) override {
     MutateCheck();
     GetMutableImpl()->DeleteStates(dstates);
index 05ad15a..1f2e963 100644 (file)
@@ -28,9 +28,6 @@ class PairWeight {
 
   PairWeight() {}
 
-  PairWeight(const PairWeight &weight)
-      : value1_(weight.value1_), value2_(weight.value2_) {}
-
   PairWeight(W1 w1, W2 w2) : value1_(std::move(w1)), value2_(std::move(w2)) {}
 
   static const PairWeight<W1, W2> &Zero() {
@@ -58,12 +55,6 @@ class PairWeight {
     return value2_.Write(strm);
   }
 
-  PairWeight<W1, W2> &operator=(const PairWeight<W1, W2> &weight) {
-    value1_ = weight.Value1();
-    value2_ = weight.Value2();
-    return *this;
-  }
-
   bool Member() const { return value1_.Member() && value2_.Member(); }
 
   size_t Hash() const {
index 63e8cd5..5a82cf1 100644 (file)
@@ -22,7 +22,7 @@ class ProjectMapper {
   using FromArc = A;
   using ToArc = A;
 
-  explicit ProjectMapper(ProjectType project_type)
+  constexpr explicit ProjectMapper(ProjectType project_type)
       : project_type_(project_type) {}
 
   ToArc operator()(const FromArc &arc) const {
@@ -34,17 +34,17 @@ class ProjectMapper {
     return MAP_NO_SUPERFINAL;
   }
 
-  MapSymbolsAction InputSymbolsAction() const {
+  constexpr MapSymbolsAction InputSymbolsAction() const {
     return project_type_ == PROJECT_INPUT ? MAP_COPY_SYMBOLS
                                           : MAP_CLEAR_SYMBOLS;
   }
 
-  MapSymbolsAction OutputSymbolsAction() const {
+  constexpr MapSymbolsAction OutputSymbolsAction() const {
     return project_type_ == PROJECT_OUTPUT ? MAP_COPY_SYMBOLS
                                            : MAP_CLEAR_SYMBOLS;
   }
 
-  uint64 Properties(uint64 props) const {
+  constexpr uint64 Properties(uint64 props) const {
     return ProjectProperties(props, project_type_ == PROJECT_INPUT);
   }
 
index bee0476..7e9130f 100644 (file)
@@ -670,7 +670,7 @@ void AutoQueue<StateId>::SccQueueType(const Fst<Arc> &fst,
 // algorithm.
 template <typename StateId, typename Weight>
 struct TrivialAStarEstimate {
-  const Weight &operator()(StateId) const { return Weight::One(); }
+  constexpr Weight operator()(StateId) const { return Weight::One(); }
 };
 
 // A non-trivial A* estimate using a vector of the estimated future costs.
index d312ef1..ee15319 100644 (file)
@@ -394,7 +394,7 @@ class RandGenFstImpl : public CacheImpl<ToArc> {
   using FstImpl<ToArc>::SetInputSymbols;
   using FstImpl<ToArc>::SetOutputSymbols;
 
-  using CacheBaseImpl<CacheState<ToArc>>::PushArc;
+  using CacheBaseImpl<CacheState<ToArc>>::EmplaceArc;
   using CacheBaseImpl<CacheState<ToArc>>::HasArcs;
   using CacheBaseImpl<CacheState<ToArc>>::HasFinal;
   using CacheBaseImpl<CacheState<ToArc>>::HasStart;
@@ -506,10 +506,10 @@ class RandGenFstImpl : public CacheImpl<ToArc> {
       if (pos < narcs) {  // Regular transition.
         aiter.Seek(sample_pair.first);
         const auto &aarc = aiter.Value();
-        const auto weight =
+        auto weight =
             weighted_ ? to_weight_(Log64Weight(-log(prob))) : ToWeight::One();
-        const ToArc barc(aarc.ilabel, aarc.olabel, weight, state_table_.size());
-        PushArc(s, barc);
+        EmplaceArc(s, aarc.ilabel, aarc.olabel, std::move(weight),
+                   state_table_.size());
         auto *nrstate = new RandState<FromArc>(aarc.nextstate, count,
                                                rstate.length + 1, pos, &rstate);
         state_table_.emplace_back(nrstate);
@@ -527,8 +527,7 @@ class RandGenFstImpl : public CacheImpl<ToArc> {
                 new RandState<FromArc>(kNoStateId, 0, 0, 0, nullptr));
           }
           for (size_t n = 0; n < count; ++n) {
-            const ToArc barc(0, 0, ToWeight::One(), superfinal_);
-            PushArc(s, barc);
+            EmplaceArc(s, 0, 0, ToWeight::One(), superfinal_);
           }
         }
       }
index 5a9e602..184ebf3 100644 (file)
@@ -61,7 +61,7 @@ class RationalFstImpl : public FstImpl<A> {
   explicit RationalFstImpl(const RationalFstOptions &opts)
       : nonterminals_(0), replace_options_(opts, 0) {
     SetType("rational");
-    fst_tuples_.push_back(std::make_pair(0, nullptr));
+    fst_tuples_.emplace_back(0, nullptr);
   }
 
   RationalFstImpl(const RationalFstImpl<Arc> &impl)
@@ -117,10 +117,10 @@ class RationalFstImpl : public FstImpl<A> {
     rfst_.SetInputSymbols(fst1.InputSymbols());
     rfst_.SetOutputSymbols(fst1.OutputSymbols());
     nonterminals_ = 2;
-    rfst_.AddArc(0, Arc(0, -1, Weight::One(), 1));
-    rfst_.AddArc(0, Arc(0, -2, Weight::One(), 1));
-    fst_tuples_.push_back(std::make_pair(-1, fst1.Copy()));
-    fst_tuples_.push_back(std::make_pair(-2, fst2.Copy()));
+    rfst_.EmplaceArc(0, 0, -1, Weight::One(), 1);
+    rfst_.EmplaceArc(0, 0, -2, Weight::One(), 1);
+    fst_tuples_.emplace_back(-1, fst1.Copy());
+    fst_tuples_.emplace_back(-2, fst2.Copy());
     SetProperties(UnionProperties(props1, props2, true), kCopyProperties);
   }
 
@@ -139,10 +139,10 @@ class RationalFstImpl : public FstImpl<A> {
     rfst_.SetInputSymbols(fst1.InputSymbols());
     rfst_.SetOutputSymbols(fst1.OutputSymbols());
     nonterminals_ = 2;
-    rfst_.AddArc(0, Arc(0, -1, Weight::One(), 1));
-    rfst_.AddArc(1, Arc(0, -2, Weight::One(), 2));
-    fst_tuples_.push_back(std::make_pair(-1, fst1.Copy()));
-    fst_tuples_.push_back(std::make_pair(-2, fst2.Copy()));
+    rfst_.EmplaceArc(0, 0, -1, Weight::One(), 1);
+    rfst_.EmplaceArc(1, 0, -2, Weight::One(), 2);
+    fst_tuples_.emplace_back(-1, fst1.Copy());
+    fst_tuples_.emplace_back(-2, fst2.Copy());
     SetProperties(ConcatProperties(props1, props2, true), kCopyProperties);
   }
 
@@ -156,18 +156,18 @@ class RationalFstImpl : public FstImpl<A> {
       rfst_.AddState();
       rfst_.SetStart(0);
       rfst_.SetFinal(0, Weight::One());
-      rfst_.AddArc(0, Arc(0, -1, Weight::One(), 0));
+      rfst_.EmplaceArc(0, 0, -1, Weight::One(), 0);
     } else {
       rfst_.AddState();
       rfst_.AddState();
       rfst_.SetStart(0);
       rfst_.SetFinal(1, Weight::One());
-      rfst_.AddArc(0, Arc(0, -1, Weight::One(), 1));
-      rfst_.AddArc(1, Arc(0, 0, Weight::One(), 0));
+      rfst_.EmplaceArc(0, 0, -1, Weight::One(), 1);
+      rfst_.EmplaceArc(1, 0, 0, Weight::One(), 0);
     }
     rfst_.SetInputSymbols(fst.InputSymbols());
     rfst_.SetOutputSymbols(fst.OutputSymbols());
-    fst_tuples_.push_back(std::make_pair(-1, fst.Copy()));
+    fst_tuples_.emplace_back(-1, fst.Copy());
     nonterminals_ = 1;
     SetProperties(ClosureProperties(props, closure_type == CLOSURE_STAR, true),
                   kCopyProperties);
@@ -184,9 +184,9 @@ class RationalFstImpl : public FstImpl<A> {
     afst.SetStart(0);
     afst.SetFinal(1, Weight::One());
     ++nonterminals_;
-    afst.AddArc(0, Arc(0, -nonterminals_, Weight::One(), 1));
+    afst.EmplaceArc(0, 0, -nonterminals_, Weight::One(), 1);
     Union(&rfst_, afst);
-    fst_tuples_.push_back(std::make_pair(-nonterminals_, fst.Copy()));
+    fst_tuples_.emplace_back(-nonterminals_, fst.Copy());
     SetProperties(UnionProperties(props1, props2, true), kCopyProperties);
   }
 
@@ -201,13 +201,13 @@ class RationalFstImpl : public FstImpl<A> {
     afst.SetStart(0);
     afst.SetFinal(1, Weight::One());
     ++nonterminals_;
-    afst.AddArc(0, Arc(0, -nonterminals_, Weight::One(), 1));
+    afst.EmplaceArc(0, 0, -nonterminals_, Weight::One(), 1);
     if (append) {
       Concat(&rfst_, afst);
     } else {
       Concat(afst, &rfst_);
     }
-    fst_tuples_.push_back(std::make_pair(-nonterminals_, fst.Copy()));
+    fst_tuples_.emplace_back(-nonterminals_, fst.Copy());
     SetProperties(ConcatProperties(props1, props2, true), kCopyProperties);
   }
 
index 9a6ac8f..0979b07 100644 (file)
@@ -35,10 +35,10 @@ void Relabel(
   using Label = typename Arc::Label;
   const auto props = fst->Properties(kFstProperties, false);
   // Constructs label-to-label maps.
-  const std::unordered_map<Label, Label>
-      input_map(ipairs.begin(), ipairs.end());
-  const std::unordered_map<Label, Label>
-      output_map(opairs.begin(), opairs.end());
+  const std::unordered_map<Label, Label> input_map(
+      ipairs.begin(), ipairs.end());
+  const std::unordered_map<Label, Label> output_map(
+      opairs.begin(), opairs.end());
   for (StateIterator<MutableFst<Arc>> siter(*fst); !siter.Done();
        siter.Next()) {
     for (MutableArcIterator<MutableFst<Arc>> aiter(fst, siter.Value());
@@ -336,7 +336,7 @@ class RelabelFstImpl : public CacheImpl<Arc> {
           arc.olabel = it->second;
         }
       }
-      PushArc(s, arc);
+      PushArc(s, std::move(arc));
     }
     SetArcs(s);
   }
index f4e1562..42c6982 100644 (file)
@@ -349,7 +349,7 @@ void ReplaceUtil<Arc>::GetDependencies(bool stats) const {
         auto it = nonterminal_hash_.find(arc.olabel);
         if (it != nonterminal_hash_.end()) {
           const auto j = it->second;
-          depfst_.AddArc(i, Arc(arc.olabel, arc.olabel, Weight::One(), j));
+          depfst_.EmplaceArc(i, arc.olabel, arc.olabel, Weight::One(), j);
           if (have_stats_) {
             ++stats_[i].nnonterms;
             ++stats_[j].nref;
@@ -475,7 +475,7 @@ void ReplaceUtil<Arc>::ReplaceLabels(const std::vector<Label> &labels) {
       if (label_set.count(label) > 0) arcs.push_back(arc);
     }
     pfst.DeleteArcs(i);
-    for (const auto &arc : arcs) pfst.AddArc(i, arc);
+    for (auto &arc : arcs) pfst.AddArc(i, std::move(arc));
   }
   std::vector<Label> toporder;
   if (!GetTopOrder(pfst, &toporder)) {
index 928c4da..8b6b18c 100644 (file)
@@ -736,10 +736,10 @@ class ReplaceFstImpl
     ArcIterator<Fst<Arc>> aiter(*fst_array_[tuple.fst_id], tuple.fst_state);
     Arc arc;
     // Creates a final arc when needed.
-    if (ComputeFinalArc(tuple, &arc)) PushArc(s, arc);
+    if (ComputeFinalArc(tuple, &arc)) PushArc(s, std::move(arc));
     // Expands all arcs leaving the state.
     for (; !aiter.Done(); aiter.Next()) {
-      if (ComputeArc(tuple, aiter.Value(), &arc)) PushArc(s, arc);
+      if (ComputeArc(tuple, aiter.Value(), &arc)) PushArc(s, std::move(arc));
     }
     SetArcs(s);
   }
index 4606101..2f29bdb 100644 (file)
@@ -156,7 +156,7 @@ void RmEpsilonState<Arc, Queue>::Expand(typename Arc::StateId source) {
         auto insert_result = element_map_.insert(
             std::make_pair(element, std::make_pair(expand_id_, arcs_.size())));
         if (insert_result.second) {
-          arcs_.push_back(arc);
+          arcs_.push_back(std::move(arc));
         } else {
           if (insert_result.first->second.first == expand_id_) {
             auto &weight = arcs_[insert_result.first->second.second].weight;
@@ -164,7 +164,7 @@ void RmEpsilonState<Arc, Queue>::Expand(typename Arc::StateId source) {
           } else {
             insert_result.first->second.first = expand_id_;
             insert_result.first->second.second = arcs_.size();
-            arcs_.push_back(arc);
+            arcs_.push_back(std::move(arc));
           }
         }
       }
@@ -431,7 +431,7 @@ class RmEpsilonFstImpl : public CacheImpl<Arc> {
     SetFinal(s, rmeps_state_.Final());
     auto &arcs = rmeps_state_.Arcs();
     while (!arcs.empty()) {
-      PushArc(s, arcs.back());
+      PushArc(s, std::move(arcs.back()));
       arcs.pop_back();
     }
     SetArcs(s);
index 0342a8d..0f4cb40 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef FST_SHORTEST_DISTANCE_H_
 #define FST_SHORTEST_DISTANCE_H_
 
-#include <deque>
+#include <cstddef>
 #include <vector>
 
 #include <fst/log.h>
@@ -80,6 +80,13 @@ class ShortestDistanceState {
         source_id_(0),
         error_(false) {
     distance_->clear();
+    if (fst.Properties(kExpanded, false) == kExpanded) {
+      const auto num_states = CountStates(fst);
+      distance_->reserve(num_states);
+      adder_.reserve(num_states);
+      radder_.reserve(num_states);
+      enqueued_.reserve(num_states);
+    }
   }
 
   void ShortestDistance(StateId source);
@@ -87,6 +94,23 @@ class ShortestDistanceState {
   bool Error() const { return error_; }
 
  private:
+  void EnsureDistanceIndexIsValid(std::size_t index) {
+    while (distance_->size() <= index) {
+      distance_->push_back(Weight::Zero());
+      adder_.push_back(Adder<Weight>());
+      radder_.push_back(Adder<Weight>());
+      enqueued_.push_back(false);
+    }
+    DCHECK_LT(index, distance_->size());
+  }
+
+  void EnsureSourcesIndexIsValid(std::size_t index) {
+    while (sources_.size() <= index) {
+      sources_.push_back(kNoStateId);
+    }
+    DCHECK_LT(index, sources_.size());
+  }
+
   const Fst<Arc> &fst_;
   std::vector<Weight> *distance_;
   Queue *state_queue_;
@@ -133,14 +157,9 @@ void ShortestDistanceState<Arc, Queue, ArcFilter>::ShortestDistance(
     enqueued_.clear();
   }
   if (source == kNoStateId) source = fst_.Start();
-  while (distance_->size() <= source) {
-    distance_->push_back(Weight::Zero());
-    adder_.push_back(Adder<Weight>());
-    radder_.push_back(Adder<Weight>());
-    enqueued_.push_back(false);
-  }
+  EnsureDistanceIndexIsValid(source);
   if (retain_) {
-    while (sources_.size() <= source) sources_.push_back(kNoStateId);
+    EnsureSourcesIndexIsValid(source);
     sources_[source] = source_id_;
   }
   (*distance_)[source] = Weight::One();
@@ -151,12 +170,7 @@ void ShortestDistanceState<Arc, Queue, ArcFilter>::ShortestDistance(
   while (!state_queue_->Empty()) {
     const auto state = state_queue_->Head();
     state_queue_->Dequeue();
-    while (distance_->size() <= state) {
-      distance_->push_back(Weight::Zero());
-      adder_.push_back(Adder<Weight>());
-      radder_.push_back(Adder<Weight>());
-      enqueued_.push_back(false);
-    }
+    EnsureDistanceIndexIsValid(state);
     if (first_path_ && (fst_.Final(state) != Weight::Zero())) break;
     enqueued_[state] = false;
     const auto r = radder_[state].Sum();
@@ -164,26 +178,22 @@ void ShortestDistanceState<Arc, Queue, ArcFilter>::ShortestDistance(
     for (ArcIterator<Fst<Arc>> aiter(fst_, state); !aiter.Done();
          aiter.Next()) {
       const auto &arc = aiter.Value();
+      const auto nextstate = arc.nextstate;
       if (!arc_filter_(arc)) continue;
-      while (distance_->size() <= arc.nextstate) {
-        distance_->push_back(Weight::Zero());
-        adder_.push_back(Adder<Weight>());
-        radder_.push_back(Adder<Weight>());
-        enqueued_.push_back(false);
-      }
+      EnsureDistanceIndexIsValid(nextstate);
       if (retain_) {
-        while (sources_.size() <= arc.nextstate) sources_.push_back(kNoStateId);
-        if (sources_[arc.nextstate] != source_id_) {
-          (*distance_)[arc.nextstate] = Weight::Zero();
-          adder_[arc.nextstate].Reset();
-          radder_[arc.nextstate].Reset();
-          enqueued_[arc.nextstate] = false;
-          sources_[arc.nextstate] = source_id_;
+        EnsureSourcesIndexIsValid(nextstate);
+        if (sources_[nextstate] != source_id_) {
+          (*distance_)[nextstate] = Weight::Zero();
+          adder_[nextstate].Reset();
+          radder_[nextstate].Reset();
+          enqueued_[nextstate] = false;
+          sources_[nextstate] = source_id_;
         }
       }
-      auto &nd = (*distance_)[arc.nextstate];
-      auto &na = adder_[arc.nextstate];
-      auto &nr = radder_[arc.nextstate];
+      auto &nd = (*distance_)[nextstate];
+      auto &na = adder_[nextstate];
+      auto &nr = radder_[nextstate];
       auto weight = Times(r, arc.weight);
       if (!ApproxEqual(nd, Plus(nd, weight), delta_)) {
         nd = na.Add(weight);
@@ -192,11 +202,11 @@ void ShortestDistanceState<Arc, Queue, ArcFilter>::ShortestDistance(
           error_ = true;
           return;
         }
-        if (!enqueued_[arc.nextstate]) {
-          state_queue_->Enqueue(arc.nextstate);
-          enqueued_[arc.nextstate] = true;
+        if (!enqueued_[nextstate]) {
+          state_queue_->Enqueue(nextstate);
+          enqueued_[nextstate] = true;
         } else {
-          state_queue_->Update(arc.nextstate);
+          state_queue_->Update(nextstate);
         }
       }
     }
@@ -238,8 +248,7 @@ void ShortestDistance(
                                                                   opts, false);
   sd_state.ShortestDistance(opts.source);
   if (sd_state.Error()) {
-    distance->clear();
-    distance->resize(1, Arc::Weight::NoWeight());
+    distance->assign(1, Arc::Weight::NoWeight());
   }
 }
 
@@ -297,9 +306,11 @@ void ShortestDistance(const Fst<Arc> &fst,
     ShortestDistance(rfst, &rdistance, ropts);
     distance->clear();
     if (rdistance.size() == 1 && !rdistance[0].Member()) {
-      distance->resize(1, Arc::Weight::NoWeight());
+      distance->assign(1, Arc::Weight::NoWeight());
       return;
     }
+    DCHECK_GE(rdistance.size(), 1);  // reversing added one state
+    distance->reserve(rdistance.size() - 1);
     while (distance->size() < rdistance.size() - 1) {
       distance->push_back(rdistance[distance->size() + 1].Reverse());
     }
index e9ba140..7bd0471 100644 (file)
@@ -89,7 +89,7 @@ void SingleShortestPathBacktrace(
       aiter.Seek(parent[d].second);
       auto arc = aiter.Value();
       arc.nextstate = d_p;
-      ofst->AddArc(s_p, arc);
+      ofst->AddArc(s_p, std::move(arc));
     }
   }
   ofst->SetStart(s_p);
@@ -197,10 +197,10 @@ bool SingleShortestPath(
   while (distance->size() < source) {
     distance->push_back(Weight::Zero());
     enqueued.push_back(false);
-    parent->push_back(std::make_pair(kNoStateId, kNoArc));
+    parent->emplace_back(kNoStateId, kNoArc);
   }
   distance->push_back(Weight::One());
-  parent->push_back(std::make_pair(kNoStateId, kNoArc));
+  parent->emplace_back(kNoStateId, kNoArc);
   state_queue->Enqueue(source);
   enqueued.push_back(true);
   while (!state_queue->Empty()) {
@@ -229,7 +229,7 @@ bool SingleShortestPath(
       while (distance->size() <= arc.nextstate) {
         distance->push_back(Weight::Zero());
         enqueued.push_back(false);
-        parent->push_back(std::make_pair(kNoStateId, kNoArc));
+        parent->emplace_back(kNoStateId, kNoArc);
       }
       auto &nd = (*distance)[arc.nextstate];
       const auto weight = Times(sd, arc.weight);
@@ -401,7 +401,7 @@ void NShortestPath(const Fst<RevArc> &ifst, MutableFst<Arc> *ofst,
       const auto next = ofst->AddState();
       pairs.push_back(std::make_pair(arc.nextstate, weight));
       arc.nextstate = state;
-      ofst->AddArc(next, arc);
+      ofst->AddArc(next, std::move(arc));
       heap.push_back(next);
       std::push_heap(heap.begin(), heap.end(), compare);
     }
index 4d13728..41339bc 100644 (file)
@@ -29,9 +29,7 @@ class SignedLogWeightTpl : public PairWeight<TropicalWeight, LogWeightTpl<T>> {
   using PairWeight<X1, X2>::Value1;
   using PairWeight<X1, X2>::Value2;
 
-  SignedLogWeightTpl() : PairWeight<X1, X2>() {}
-
-  SignedLogWeightTpl(const SignedLogWeightTpl &w) : PairWeight<X1, X2>(w) {}
+  SignedLogWeightTpl() noexcept : PairWeight<X1, X2>() {}
 
   explicit SignedLogWeightTpl(const PairWeight<X1, X2> &w)
       : PairWeight<X1, X2>(w) {}
@@ -59,6 +57,8 @@ class SignedLogWeightTpl : public PairWeight<TropicalWeight, LogWeightTpl<T>> {
     return *type;
   }
 
+  bool IsPositive() const { return Value1().Value() > 0; }
+
   SignedLogWeightTpl Quantize(float delta = kDelta) const {
     return SignedLogWeightTpl(PairWeight<X1, X2>::Quantize(delta));
   }
@@ -76,7 +76,7 @@ class SignedLogWeightTpl : public PairWeight<TropicalWeight, LogWeightTpl<T>> {
 
   size_t Hash() const {
     size_t h1;
-    if (Value2() == X2::Zero() || Value1().Value() > 0.0) {
+    if (Value2() == X2::Zero() || IsPositive()) {
       h1 = TropicalWeight(1.0).Hash();
     } else {
       h1 = TropicalWeight(-1.0).Hash();
@@ -94,8 +94,8 @@ inline SignedLogWeightTpl<T> Plus(const SignedLogWeightTpl<T> &w1,
   using X1 = TropicalWeight;
   using X2 = LogWeightTpl<T>;
   if (!w1.Member() || !w2.Member()) return SignedLogWeightTpl<T>::NoWeight();
-  const auto s1 = w1.Value1().Value() > 0.0;
-  const auto s2 = w2.Value1().Value() > 0.0;
+  const auto s1 = w1.IsPositive();
+  const auto s2 = w2.IsPositive();
   const bool equal = (s1 == s2);
   const auto f1 = w1.Value2().Value();
   const auto f2 = w2.Value2().Value();
@@ -140,8 +140,8 @@ inline SignedLogWeightTpl<T> Times(const SignedLogWeightTpl<T> &w1,
                                    const SignedLogWeightTpl<T> &w2) {
   using X2 = LogWeightTpl<T>;
   if (!w1.Member() || !w2.Member()) return SignedLogWeightTpl<T>::NoWeight();
-  const auto s1 = w1.Value1().Value() > 0.0;
-  const auto s2 = w2.Value1().Value() > 0.0;
+  const auto s1 = w1.IsPositive();
+  const auto s2 = w2.IsPositive();
   const auto f1 = w1.Value2().Value();
   const auto f2 = w2.Value2().Value();
   if (s1 == s2) {
@@ -157,8 +157,8 @@ inline SignedLogWeightTpl<T> Divide(const SignedLogWeightTpl<T> &w1,
                                     DivideType typ = DIVIDE_ANY) {
   using X2 = LogWeightTpl<T>;
   if (!w1.Member() || !w2.Member()) return SignedLogWeightTpl<T>::NoWeight();
-  const auto s1 = w1.Value1().Value() > 0.0;
-  const auto s2 = w2.Value1().Value() > 0.0;
+  const auto s1 = w1.IsPositive();
+  const auto s2 = w2.IsPositive();
   const auto f1 = w1.Value2().Value();
   const auto f2 = w2.Value2().Value();
   if (f2 == FloatLimits<T>::PosInfinity()) {
@@ -177,29 +177,33 @@ inline SignedLogWeightTpl<T> Divide(const SignedLogWeightTpl<T> &w1,
 template <class T>
 inline bool ApproxEqual(const SignedLogWeightTpl<T> &w1,
                         const SignedLogWeightTpl<T> &w2, float delta = kDelta) {
-  const auto s1 = w1.Value1().Value() > 0.0;
-  const auto s2 = w2.Value1().Value() > 0.0;
-  if (s1 == s2) {
+  using X2 = LogWeightTpl<T>;
+  if (w1.IsPositive() == w2.IsPositive()) {
     return ApproxEqual(w1.Value2(), w2.Value2(), delta);
   } else {
-    return w1.Value2() == LogWeightTpl<T>::Zero() &&
-           w2.Value2() == LogWeightTpl<T>::Zero();
+    return ApproxEqual(w1.Value2(), X2::Zero(), delta)
+        && ApproxEqual(w2.Value2(), X2::Zero(), delta);
   }
 }
 
 template <class T>
 inline bool operator==(const SignedLogWeightTpl<T> &w1,
                        const SignedLogWeightTpl<T> &w2) {
-  const auto s1 = w1.Value1().Value() > 0.0;
-  const auto s2 = w2.Value1().Value() > 0.0;
-  if (s1 == s2) {
+  using X2 = LogWeightTpl<T>;
+  if (w1.IsPositive() == w2.IsPositive()) {
     return w1.Value2() == w2.Value2();
   } else {
-    return (w1.Value2() == LogWeightTpl<T>::Zero()) &&
-           (w2.Value2() == LogWeightTpl<T>::Zero());
+    return w1.Value2() == X2::Zero()
+        && w2.Value2() == X2::Zero();
   }
 }
 
+template <class T>
+inline bool operator!=(const SignedLogWeightTpl<T> &w1,
+                       const SignedLogWeightTpl<T> &w2) {
+  return !(w1 == w2);
+}
+
 // Single-precision signed-log weight.
 using SignedLogWeight = SignedLogWeightTpl<float>;
 
@@ -225,12 +229,12 @@ class Adder<SignedLogWeightTpl<T>> {
   using X2 = LogWeightTpl<T>;
 
   explicit Adder(Weight w = Weight::Zero())
-     : ssum_(w.Value1().Value() > 0.0),
+      : ssum_(w.IsPositive()),
         sum_(w.Value2().Value()),
         c_(0.0) { }
 
   Weight Add(const Weight &w) {
-    const auto sw = w.Value1().Value() > 0.0;
+    const auto sw = w.IsPositive();
     const auto f = w.Value2().Value();
     const bool equal = (ssum_ == sw);
 
@@ -268,7 +272,7 @@ class Adder<SignedLogWeightTpl<T>> {
   Weight Sum() { return Weight(X1(ssum_ ? 1.0 : -1.0), X2(sum_)); }
 
   void Reset(Weight w = Weight::Zero()) {
-    ssum_ = w.Value1().Value() > 0.0;
+    ssum_ = w.IsPositive();
     sum_ = w.Value2().Value();
     c_ = 0.0;
   }
index 0665ca2..68c9c66 100644 (file)
@@ -47,6 +47,8 @@ class SparseTupleWeight {
 
   SparseTupleWeight() { Init(); }
 
+  ~SparseTupleWeight() noexcept = default;
+
   template <class Iterator>
   SparseTupleWeight(Iterator begin, Iterator end) {
     Init();
@@ -70,10 +72,11 @@ class SparseTupleWeight {
     }
   }
 
-  SparseTupleWeight(SparseTupleWeight &&weight)
-    // Don't move the default, so weight.default_ is still valid.
-    : default_(weight.default_), first_(std::move(weight.first_)),
-      rest_(std::move(weight.rest_)) {
+  SparseTupleWeight(SparseTupleWeight &&weight) noexcept
+      // Don't move the default, so weight.default_ is still valid.
+      : default_(weight.default_),  // NOLINT
+        first_(std::move(weight.first_)),
+        rest_(std::move(weight.rest_)) {
     // move leaves the source in a valid but unspecified state.
     // Make sure the source weight is empty.
     weight.first_ = Pair(kNoKey, W::NoWeight());
@@ -116,11 +119,16 @@ class SparseTupleWeight {
     return *this;
   }
 
-  SparseTupleWeight &operator=(SparseTupleWeight &&weight) {
+  SparseTupleWeight &operator=(SparseTupleWeight &&weight) noexcept {
     if (this == &weight) return *this;  // Checks for identity.
+    // Don't move the default, so weight.default_ is still valid.
     default_ = weight.default_;
-    std::swap(first_, weight.first_);
-    std::swap(rest_, weight.rest_);
+    first_ = std::move(weight.first_);
+    rest_ = std::move(weight.rest_);
+    // move leaves the source in a valid but unspecified state.
+    // Make sure the source weight is empty.
+    weight.first_ = Pair(kNoKey, W::NoWeight());
+    weight.rest_.clear();
     return *this;
   }
 
@@ -152,11 +160,11 @@ class SparseTupleWeight {
   }
 
   ReverseWeight Reverse() const {
-    SparseTupleWeight weight;
+    ReverseWeight weight(DefaultValue().Reverse());
     for (Iterator it(*this); !it.Done(); it.Next()) {
       weight.PushBack(it.Value().first, it.Value().second.Reverse());
     }
-    return ReverseWeight(weight);
+    return weight;
   }
 
   void Init(const W &default_value = W::Zero()) {
index adb1d84..f634dae 100644 (file)
@@ -61,7 +61,8 @@ bool ConvertStringToLabels(const string &str, StringTokenType token_type,
                            bool allow_negative, std::vector<Label> *labels) {
   labels->clear();
   if (token_type == StringTokenType::BYTE) {
-    for (const char c : str) labels->push_back(c);
+    labels->reserve(str.size());
+    for (const char c : str) labels->push_back(static_cast<unsigned char>(c));
   } else if (token_type == StringTokenType::UTF8) {
     return UTF8StringToLabels(str, labels);
   } else {
index f861a4a..1a86ba2 100644 (file)
@@ -183,7 +183,7 @@ class SymbolTableImpl {
   std::vector<int64> idx_key_;
   // Maps key to index for key >= dense_key_limit_.
   //  index = key_map_[key]
-  map<int64, int64> key_map_;
+  std::map<int64, int64> key_map_;
 
   mutable bool check_sum_finalized_;
   mutable string check_sum_string_;
index b2fc3df..0c1c686 100644 (file)
@@ -38,7 +38,7 @@ class SynchronizeFstImpl : public CacheImpl<Arc> {
   using FstImpl<Arc>::SetInputSymbols;
   using FstImpl<Arc>::SetOutputSymbols;
 
-  using CacheBaseImpl<CacheState<Arc>>::PushArc;
+  using CacheBaseImpl<CacheState<Arc>>::EmplaceArc;
   using CacheBaseImpl<CacheState<Arc>>::HasArcs;
   using CacheBaseImpl<CacheState<Arc>>::HasFinal;
   using CacheBaseImpl<CacheState<Arc>>::HasStart;
@@ -209,14 +209,14 @@ class SynchronizeFstImpl : public CacheImpl<Arc> {
             !Empty(element.ostring, arc.olabel)) {
           const auto *istring = Cdr(element.istring, arc.ilabel);
           const auto *ostring = Cdr(element.ostring, arc.olabel);
-          PushArc(s, Arc(Car(element.istring, arc.ilabel),
-                         Car(element.ostring, arc.olabel), arc.weight,
-                         FindState(Element(arc.nextstate, istring, ostring))));
+          EmplaceArc(s, Car(element.istring, arc.ilabel),
+                     Car(element.ostring, arc.olabel), arc.weight,
+                     FindState(Element(arc.nextstate, istring, ostring)));
         } else {
           const auto *istring = Concat(element.istring, arc.ilabel);
           const auto *ostring = Concat(element.ostring, arc.olabel);
-          PushArc(s, Arc(0, 0, arc.weight,
-                         FindState(Element(arc.nextstate, istring, ostring))));
+          EmplaceArc(s, 0, 0, arc.weight,
+                     FindState(Element(arc.nextstate, istring, ostring)));
         }
       }
     }
@@ -227,8 +227,8 @@ class SynchronizeFstImpl : public CacheImpl<Arc> {
         ((element.istring)->size() + (element.ostring)->size() > 0)) {
       const auto *istring = Cdr(element.istring);
       const auto *ostring = Cdr(element.ostring);
-      PushArc(s, Arc(Car(element.istring), Car(element.ostring), weight,
-                     FindState(Element(kNoStateId, istring, ostring))));
+      EmplaceArc(s, Car(element.istring), Car(element.ostring), weight,
+                 FindState(Element(kNoStateId, istring, ostring)));
     }
     SetArcs(s);
   }
index 97680e0..c8ecab7 100644 (file)
@@ -29,13 +29,6 @@ class TupleWeight {
   using Weight = W;
   using Index = size_t;
 
-  TupleWeight(const TupleWeight &other) { values_ = other.values_; }
-
-  TupleWeight<W, n> &operator=(const TupleWeight<W, n> &other) {
-    values_ = other.values_;
-    return *this;
-  }
-
   template <class Iterator>
   TupleWeight(Iterator begin, Iterator end) {
     std::copy(begin, end, values_.begin());
index 5f56c17..52aa786 100644 (file)
@@ -7,6 +7,7 @@
 #define FST_UNION_H_
 
 #include <algorithm>
+#include <utility>
 #include <vector>
 
 #include <fst/mutable-fst.h>
@@ -61,7 +62,7 @@ void Union(MutableFst<Arc> *fst1, const Fst<Arc> &fst2) {
     for (ArcIterator<Fst<Arc>> aiter(fst2, s2); !aiter.Done(); aiter.Next()) {
       auto arc = aiter.Value();  // Copy intended.
       arc.nextstate += numstates1;
-      fst1->AddArc(s1, arc);
+      fst1->AddArc(s1, std::move(arc));
     }
   }
   const auto start1 = fst1->Start();
index f75a9d4..a89b8c1 100644 (file)
@@ -25,6 +25,7 @@
 #include <fstream>
 
 #include <fst/flags.h>
+#include <unordered_map>
 
 
 // Utility for error handling.
index 49e99fd..c705e4e 100644 (file)
@@ -77,16 +77,25 @@ class VectorState {
   void SetNumOutputEpsilons(size_t n) { noepsilons_ = n; }
 
   void AddArc(const Arc &arc) {
-    if (arc.ilabel == 0) ++niepsilons_;
-    if (arc.olabel == 0) ++noepsilons_;
+    IncrementNumEpsilons(arc);
     arcs_.push_back(arc);
   }
 
+  void AddArc(Arc &&arc) {
+    IncrementNumEpsilons(arc);
+    arcs_.push_back(std::move(arc));
+  }
+
+  template <class... T>
+  void EmplaceArc(T&&... ctor_args) {
+    arcs_.emplace_back(std::forward<T>(ctor_args)...);
+    IncrementNumEpsilons(arcs_.back());
+  }
+
   void SetArc(const Arc &arc, size_t n) {
     if (arcs_[n].ilabel == 0) --niepsilons_;
     if (arcs_[n].olabel == 0) --noepsilons_;
-    if (arc.ilabel == 0) ++niepsilons_;
-    if (arc.olabel == 0) ++noepsilons_;
+    IncrementNumEpsilons(arc);
     arcs_[n] = arc;
   }
 
@@ -118,6 +127,12 @@ class VectorState {
   }
 
  private:
+  // Update the number of epsilons as a result of having added an arc.
+  void IncrementNumEpsilons(const Arc &arc) {
+    if (arc.ilabel == 0) ++niepsilons_;
+    if (arc.olabel == 0) ++noepsilons_;
+  }
+
   Weight final_;                       // Final weight.
   size_t niepsilons_;                  // # of input epsilons
   size_t noepsilons_;                  // # of output epsilons
@@ -144,6 +159,27 @@ class VectorFstBaseImpl : public FstImpl<typename S::Arc> {
     }
   }
 
+  // Copying is not permitted.
+  VectorFstBaseImpl(const VectorFstBaseImpl<S> &) = delete;
+  VectorFstBaseImpl<S> &operator=(const VectorFstBaseImpl<S> &) = delete;
+
+  // Moving is permitted.
+  VectorFstBaseImpl(VectorFstBaseImpl<S> &&impl) noexcept
+      : FstImpl<typename S::Arc>(),
+        states_(std::move(impl.states_)),
+        start_(impl.start_) {
+    impl.states_.clear();
+    impl.start_ = kNoStateId;
+  }
+
+  VectorFstBaseImpl<S> &operator=(VectorFstBaseImpl<S> &&impl) noexcept {
+    states_ = std::move(impl.states_);
+    start_ = impl.start_;
+    impl.states_.clear();
+    impl.start_ = kNoStateId;
+    return *this;
+  }
+
   StateId Start() const { return start_; }
 
   Weight Final(StateId state) const { return states_[state]->Final(); }
@@ -178,6 +214,15 @@ class VectorFstBaseImpl : public FstImpl<typename S::Arc> {
 
   void AddArc(StateId state, const Arc &arc) { states_[state]->AddArc(arc); }
 
+  void AddArc(StateId state, Arc &&arc) {
+    states_[state]->AddArc(std::move(arc));
+  }
+
+  template <class... T>
+  void EmplaceArc(StateId state, T&&... ctor_args) {
+    states_[state]->EmplaceArc(std::forward<T>(ctor_args)...);
+  }
+
   void DeleteStates(const std::vector<StateId> &dstates) {
     std::vector<StateId> newid(states_.size(), 0);
     for (StateId i = 0; i < dstates.size(); ++i) newid[dstates[i]] = kNoStateId;
@@ -256,9 +301,6 @@ class VectorFstBaseImpl : public FstImpl<typename S::Arc> {
   StateId start_;                               // Initial state.
   typename State::StateAllocator state_alloc_;  // For state allocation.
   typename State::ArcAllocator arc_alloc_;      // For arc allocation.
-
-  VectorFstBaseImpl(const VectorFstBaseImpl &) = delete;
-  VectorFstBaseImpl &operator=(const VectorFstBaseImpl &) = delete;
 };
 
 // This is a VectorFstBaseImpl container that holds VectorStates and manages FST
@@ -316,12 +358,19 @@ class VectorFstImpl : public VectorFstBaseImpl<S> {
   }
 
   void AddArc(StateId state, const Arc &arc) {
-    auto *vstate = GetState(state);
-    const auto *parc = vstate->NumArcs() == 0
-                           ? nullptr
-                           : &(vstate->GetArc(vstate->NumArcs() - 1));
-    SetProperties(AddArcProperties(Properties(), state, arc, parc));
     BaseImpl::AddArc(state, arc);
+    UpdatePropertiesAfterAddArc(state);
+  }
+
+  void AddArc(StateId state, Arc &&arc) {
+    BaseImpl::AddArc(state, std::move(arc));
+    UpdatePropertiesAfterAddArc(state);
+  }
+
+  template <class... T>
+  void EmplaceArc(StateId state, T&&... ctor_args) {
+    BaseImpl::EmplaceArc(state, std::forward<T>(ctor_args)...);
+    UpdatePropertiesAfterAddArc(state);
   }
 
   void DeleteStates(const std::vector<StateId> &dstates) {
@@ -348,6 +397,18 @@ class VectorFstImpl : public VectorFstBaseImpl<S> {
   static constexpr uint64 kStaticProperties = kExpanded | kMutable;
 
  private:
+  void UpdatePropertiesAfterAddArc(StateId state) {
+    auto *vstate = GetState(state);
+    const size_t num_arcs{vstate->NumArcs()};
+    if (num_arcs) {
+      const auto &arc = vstate->GetArc(num_arcs - 1);
+      const auto *parc = (num_arcs < 2)
+                         ? nullptr
+                         : &(vstate->GetArc(num_arcs - 2));
+      SetProperties(AddArcProperties(Properties(), state, arc, parc));
+    }
+  }
+
   // Minimum file format version supported.
   static constexpr int kMinFileVersion = 2;
 };
@@ -412,7 +473,7 @@ VectorFstImpl<S> *VectorFstImpl<S>::Read(std::istream &strm,
         LOG(ERROR) << "VectorFst::Read: Read failed: " << opts.source;
         return nullptr;
       }
-      impl->BaseImpl::AddArc(state, arc);
+      impl->BaseImpl::AddArc(state, std::move(arc));
     }
   }
   if (hdr.NumStates() != kNoStateId && state != hdr.NumStates()) {
@@ -452,21 +513,28 @@ class VectorFst : public ImplToMutableFst<internal::VectorFstImpl<S>> {
   VectorFst(const VectorFst<Arc, State> &fst, bool safe = false)
       : ImplToMutableFst<Impl>(fst) {}
 
+  VectorFst(VectorFst<Arc, State> &&) noexcept;
+
   // Get a copy of this VectorFst. See Fst<>::Copy() for further doc.
   VectorFst<Arc, State> *Copy(bool safe = false) const override {
     return new VectorFst<Arc, State>(*this, safe);
   }
 
-  VectorFst<Arc, State> &operator=(const VectorFst<Arc, State> &fst) {
-    SetImpl(fst.GetSharedImpl());
-    return *this;
-  }
+  VectorFst<Arc, State> &operator=(const VectorFst<Arc, State> &) = default;
+
+  VectorFst<Arc, State> &operator=(VectorFst<Arc, State> &&) noexcept;
 
   VectorFst<Arc, State> &operator=(const Fst<Arc> &fst) override {
     if (this != &fst) SetImpl(std::make_shared<Impl>(fst));
     return *this;
   }
 
+  template <class... T>
+  void EmplaceArc(StateId state, T&&... ctor_args) {
+    MutateCheck();
+    GetMutableImpl()->EmplaceArc(state, std::forward<T>(ctor_args)...);
+  }
+
   // Reads a VectorFst from an input stream, returning nullptr on error.
   static VectorFst<Arc, State> *Read(std::istream &strm,
                                      const FstReadOptions &opts) {
@@ -511,6 +579,7 @@ class VectorFst : public ImplToMutableFst<internal::VectorFstImpl<S>> {
 
  private:
   using ImplToMutableFst<Impl, MutableFst<Arc>>::GetImpl;
+  using ImplToMutableFst<Impl, MutableFst<Arc>>::GetMutableImpl;
   using ImplToMutableFst<Impl, MutableFst<Arc>>::MutateCheck;
   using ImplToMutableFst<Impl, MutableFst<Arc>>::SetImpl;
 
@@ -518,6 +587,14 @@ class VectorFst : public ImplToMutableFst<internal::VectorFstImpl<S>> {
       : ImplToMutableFst<Impl>(impl) {}
 };
 
+template <class Arc, class State>
+inline VectorFst<Arc, State>::VectorFst(
+    VectorFst<Arc, State> &&fst) noexcept = default;
+
+template <class Arc, class State>
+inline VectorFst<Arc, State> &VectorFst<Arc, State>::operator=(
+    VectorFst<Arc, State> &&fst) noexcept = default;
+
 // Writes FST to file in Vector format, potentially with a pass over the machine
 // before writing to compute number of states.
 template <class Arc, class State>
index 319f5a0..964ae81 100644 (file)
@@ -4,5 +4,5 @@ lib_LTLIBRARIES = libfst.la
 libfst_la_SOURCES = compat.cc flags.cc fst.cc fst-types.cc mapped-file.cc \
                     properties.cc symbol-table.cc symbol-table-ops.cc \
                     weight.cc util.cc
-libfst_la_LDFLAGS = -version-info 13:0:0
+libfst_la_LDFLAGS = -version-info 14:0:0
 libfst_la_LIBADD = $(DL_LIBS)
index 45792f1..20311a7 100644 (file)
@@ -349,7 +349,7 @@ libfst_la_SOURCES = compat.cc flags.cc fst.cc fst-types.cc mapped-file.cc \
                     properties.cc symbol-table.cc symbol-table-ops.cc \
                     weight.cc util.cc
 
-libfst_la_LDFLAGS = -version-info 13:0:0
+libfst_la_LDFLAGS = -version-info 14:0:0
 libfst_la_LIBADD = $(DL_LIBS)
 all: all-am
 
index 6e467ba..eb853a6 100644 (file)
@@ -1,4 +1,4 @@
-// Registration of common Fst and arc types.
+// Registration of common FST and arc types.
 
 #include <fst/arc.h>
 #include <fst/compact-fst.h>
@@ -9,27 +9,36 @@
 
 namespace fst {
 
-// Registers VectorFst, ConstFst and EditFst for common arcs types.
 REGISTER_FST(VectorFst, StdArc);
 REGISTER_FST(VectorFst, LogArc);
 REGISTER_FST(VectorFst, Log64Arc);
+
 REGISTER_FST(ConstFst, StdArc);
 REGISTER_FST(ConstFst, LogArc);
 REGISTER_FST(ConstFst, Log64Arc);
+
 REGISTER_FST(EditFst, StdArc);
 REGISTER_FST(EditFst, LogArc);
 REGISTER_FST(EditFst, Log64Arc);
 
-// Register CompactFst for common arcs with the default (uint32) size type
 REGISTER_FST(CompactStringFst, StdArc);
 REGISTER_FST(CompactStringFst, LogArc);
+REGISTER_FST(CompactStringFst, Log64Arc);
+
 REGISTER_FST(CompactWeightedStringFst, StdArc);
 REGISTER_FST(CompactWeightedStringFst, LogArc);
+REGISTER_FST(CompactWeightedStringFst, Log64Arc);
+
 REGISTER_FST(CompactAcceptorFst, StdArc);
 REGISTER_FST(CompactAcceptorFst, LogArc);
+REGISTER_FST(CompactAcceptorFst, Log64Arc);
+
 REGISTER_FST(CompactUnweightedFst, StdArc);
 REGISTER_FST(CompactUnweightedFst, LogArc);
+REGISTER_FST(CompactUnweightedFst, Log64Arc);
+
 REGISTER_FST(CompactUnweightedAcceptorFst, StdArc);
 REGISTER_FST(CompactUnweightedAcceptorFst, LogArc);
+REGISTER_FST(CompactUnweightedAcceptorFst, Log64Arc);
 
 }  // namespace fst
index 0c396ea..6852fa7 100644 (file)
@@ -7,6 +7,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/mman.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #include <algorithm>
@@ -42,25 +43,14 @@ MappedFile *MappedFile::Map(std::istream *istrm, bool memorymap,
           << " size: " << size << " offset: " << spos;
   if (memorymap && spos >= 0 && spos % kArchAlignment == 0) {
     const size_t pos = spos;
-    int fd = open(source.c_str(), O_RDONLY);
+    const int fd = open(source.c_str(), O_RDONLY);
     if (fd != -1) {
-      const int pagesize = sysconf(_SC_PAGESIZE);
-      const off_t offset = pos % pagesize;
-      const off_t upsize = size + offset;
-      void *map =
-          mmap(nullptr, upsize, PROT_READ, MAP_SHARED, fd, pos - offset);
-      auto *data = reinterpret_cast<char *>(map);
-      if (close(fd) == 0 && map != MAP_FAILED) {
-        MemoryRegion region;
-        region.mmap = map;
-        region.size = upsize;
-        region.data = reinterpret_cast<void *>(data + offset);
-        region.offset = offset;
-        std::unique_ptr<MappedFile> mmf(new MappedFile(region));
+      std::unique_ptr<MappedFile> mmf(MapFromFileDescriptor(fd, pos, size));
+      if (close(fd) == 0 && mmf != nullptr) {
         istrm->seekg(pos + size, std::ios::beg);
         if (istrm) {
           VLOG(1) << "mmap'ed region of " << size << " at offset " << pos
-                  << " from " << source << " to addr " << map;
+                  << " from " << source << " to addr " << mmf->region_.mmap;
           return mmf.release();
         }
       } else {
@@ -68,6 +58,7 @@ MappedFile *MappedFile::Map(std::istream *istrm, bool memorymap,
       }
     }
   }
+
   // If all else fails, reads from the file into the allocated buffer.
   if (memorymap) {
     LOG(WARNING) << "File mapping at offset " << spos << " of file " << source
@@ -91,6 +82,26 @@ MappedFile *MappedFile::Map(std::istream *istrm, bool memorymap,
   return mf.release();
 }
 
+MappedFile *MappedFile::MapFromFileDescriptor(int fd, int pos, size_t size) {
+  const int pagesize = sysconf(_SC_PAGESIZE);
+  const off_t offset = pos % pagesize;
+  const off_t upsize = size + offset;
+  void *map = mmap(nullptr, upsize, PROT_READ, MAP_SHARED, fd, pos - offset);
+  if (map == MAP_FAILED) {
+    LOG(ERROR) << "mmap failed for fd=" << fd << " size=" << upsize
+               << " offset=" << (pos - offset);
+    return nullptr;
+  }
+
+  MemoryRegion region;
+  region.mmap = map;
+  region.size = upsize;
+  region.data =
+      reinterpret_cast<void *>(reinterpret_cast<char *>(map) + offset);
+  region.offset = offset;
+  return new MappedFile(region);
+}
+
 MappedFile *MappedFile::Allocate(size_t size, int align) {
   MemoryRegion region;
   region.data = nullptr;
index 4faae72..e81d46f 100644 (file)
@@ -146,7 +146,7 @@ void SymbolTableImpl::MaybeRecomputeCheckSum() const {
     line << symbols_.GetSymbol(i) << '\t' << i;
     labeled_check_sum.Update(line.str().data(), line.str().size());
   }
-  using citer = map<int64, int64>::const_iterator;
+  using citer = std::map<int64, int64>::const_iterator;
   for (citer it = key_map_.begin(); it != key_map_.end(); ++it) {
     // TODO(tombagby, 2013-11-22) This line maintains a bug that ignores
     // negative labels in the checksum that too many tests rely on.
index bb5e9ee..ae474d2 100644 (file)
@@ -13,5 +13,5 @@ shortest-distance.cc shortest-path.cc stateiterator-class.cc synchronize.cc \
 text-io.cc topsort.cc union.cc weight-class.cc verify.cc
 
 libfstscript_la_LIBADD = ../lib/libfst.la -lm $(DL_LIBS)
-libfstscript_la_LDFLAGS = -version-info 13:0:0
+libfstscript_la_LDFLAGS = -version-info 14:0:0
 endif
index 8b0d8cb..5a0bb0a 100644 (file)
@@ -382,7 +382,7 @@ AM_CPPFLAGS = -I$(srcdir)/../include $(ICU_CPPFLAGS)
 @HAVE_SCRIPT_TRUE@text-io.cc topsort.cc union.cc weight-class.cc verify.cc
 
 @HAVE_SCRIPT_TRUE@libfstscript_la_LIBADD = ../lib/libfst.la -lm $(DL_LIBS)
-@HAVE_SCRIPT_TRUE@libfstscript_la_LDFLAGS = -version-info 13:0:0
+@HAVE_SCRIPT_TRUE@libfstscript_la_LDFLAGS = -version-info 14:0:0
 all: all-am
 
 .SUFFIXES:
index 7a349bf..d6b1922 100644 (file)
@@ -246,6 +246,34 @@ void TestSparsePowerWeightGetSetValue() {
   CHECK_EQ(default_value, w.Value(31));
 }
 
+// If this test fails, it is possible that x == x will not
+// hold for FloatWeight, breaking NaturalLess and probably more.
+// To trigger these failures, use g++ -O -m32 -mno-sse.
+// Google-only...
+// This will never fail in google3, as those options aren't used.
+// ...Google-only
+template <class T>
+bool FloatEqualityIsReflexive(T m) {
+  // The idea here is that x is spilled to memory, but
+  // y remains in an 80-bit register with extra precision,
+  // causing it to compare unequal to x.
+  volatile T x = 1.111;
+  x *= m;
+
+  T y = 1.111;
+  y *= m;
+
+  return x == y;
+}
+
+void TestFloatEqualityIsReflexive() {
+  // Use a volatile test_value to avoid excessive inlining / optimization
+  // breaking what we're trying to test.
+  volatile double test_value = 1.1;
+  CHECK(FloatEqualityIsReflexive(static_cast<float>(test_value)));
+  CHECK(FloatEqualityIsReflexive(test_value));
+}
+
 }  // namespace
 
 int main(int argc, char **argv) {
@@ -269,6 +297,7 @@ int main(int argc, char **argv) {
   CHECK(LogWeightTpl<double>::Type() != LogWeightTpl<float>::Type());
   TropicalWeightTpl<double> w(2.0);
   TropicalWeight tw(2.0);
+  CHECK_EQ(w.Value(), tw.Value());
 
   TestAdder<TropicalWeight>(1000);
   TestAdder<LogWeight>(1000);
@@ -487,6 +516,8 @@ int main(int argc, char **argv) {
   TestPowerWeightGetSetValue();
   TestSparsePowerWeightGetSetValue();
 
+  TestFloatEqualityIsReflexive();
+
   std::cout << "PASS" << std::endl;
 
   return 0;