Git Product home page Git Product logo

graphtage's Introduction

Graphtage

PyPI version Tests Slack Status

Graphtage is a command-line utility and underlying library for semantically comparing and merging tree-like structures, such as JSON, XML, HTML, YAML, plist, and CSS files. Its name is a portmanteau of “graph” and “graftage”—the latter being the horticultural practice of joining two trees together such that they grow as one.

$ echo Original: && cat original.json && echo Modified: && cat modified.json
Original:
{
    "foo": [1, 2, 3, 4],
    "bar": "testing"
}
Modified:
{
    "foo": [2, 3, 4, 5],
    "zab": "testing",
    "woo": ["foobar"]
}
$ graphtage original.json modified.json
{
    "z̟b̶ab̟r̶": "testing",
    "foo": [
        1̶,̶
        2,
        3,
        4,̟
        5̟
    ],̟
    "̟w̟o̟o̟"̟:̟ ̟[̟
        "̟f̟o̟o̟b̟a̟r̟"̟
    
}

Installation

$ pip3 install graphtage

Command Line Usage

Output Formatting

Graphtage performs an analysis on an intermediate representation of the trees that is divorced from the filetypes of the input files. This means, for example, that you can diff a JSON file against a YAML file. Also, the output format can be different from the input format(s). By default, Graphtage will format the output diff in the same file format as the first input file. But one could, for example, diff two JSON files and format the output in YAML. There are several command-line arguments to specify these transformations, such as --format; please check the --help output for more information.

By default, Graphtage pretty-prints its output with as many line breaks and indents as possible.

{
    "foo": [
        1,
        2,
        3
    ],
    "bar": "baz"
}

Use the --join-lists or -jl option to suppress linebreaks after list items:

{
    "foo": [1, 2, 3],
    "bar": "baz"
}

Likewise, use the --join-dict-items or -jd option to suppress linebreaks after key/value pairs in a dict:

{"foo": [
    1,
    2,
    3
], "bar":  "baz"}

Use --condensed or -j to apply both of these options:

{"foo": [1, 2, 3], "bar": "baz"}

The --only-edits or -e option will print out a list of edits rather than applying them to the input file in place.

The --edit-digest or -d option is like --only-edits but prints a more concise context for each edit that is more human-readable.

Matching Options

By default, Graphtage tries to match all possible pairs of elements in a dictionary.

Matching two dictionaries with each other is hard. Although computationally tractable, this can sometimes be onerous for input files with huge dictionaries. Graphtage has three different strategies for matching dictionaries:

  1. --dict-strategy match (the most computationally expensive) tries to match all pairs of keys and values between the two dictionaries, resulting in a match of minimum edit distance;
  2. --dict-strategy none (the least computationally expensive) will not attempt to match any key/value pairs unless they have the exact same key; and
  3. --dict-strategy auto (the default) will automatically match the values of any key-value pairs that have identical keys and then use the match strategy for the remainder of key/value pairs.

See Pull Request #51 for some examples of how these strategies affect output.

The --no-list-edits or -l option will not consider interstitial insertions and removals when comparing two lists. The --no-list-edits-when-same-length or -ll option is a less drastic version of -l that will behave normally for lists that are of different lengths but behave like -l for lists that are of the same length.

ANSI Color

By default, Graphtage will only use ANSI color in its output if it is run from a TTY. If, for example, you would like to have Graphtage emit colorized output from a script or pipe, use the --color or -c argument. To disable color even when running on a TTY, use --no-color.

HTML Output

Graphtage can optionally emit the diff in HTML with the --html option.

$ graphtage --html original.json modified.json > diff.html

Status and Logging

By default, Graphtage prints status messages and a progress bar to STDERR. To suppress this, use the --no-status option. To additionally suppress all but critical log messages, use --quiet. Fine-grained control of log messages is via the --log-level option.

Why does Graphtage exist?

Diffing tree-like structures with unordered elements is tough. Say you want to compare two JSON files. There are limited tools available, which are effectively equivalent to canonicalizing the JSON (e.g., sorting dictionary elements by key) and performing a standard diff. This is not always sufficient. For example, if a key in a dictionary is changed but its value is not, a traditional diff will conclude that the entire key/value pair was replaced by the new one, even though the only change was the key itself. See our documentation for more information.

Using Graphtage as a Library

Graphtage has a complete API for programmatically operating its diffing capabilities. When using Graphtage as a library, it is also capable of diffing in-memory Python objects. This can be useful for debugging Python code, for example, to determine a differential between two objects. See our documentation for more information.

Extending Graphtage

Graphtage is designed to be extensible: New filetypes can easily be defined, as well as new node types, edit types, formatters, and printers. See our documentation for more information.

Complete API documentation is available here.

License and Acknowledgements

This research was developed by Trail of Bits with partial funding from the Defense Advanced Research Projects Agency (DARPA) under the SafeDocs program as a subcontractor to Galois. It is licensed under the GNU Lesser General Public License v3.0. Contact us if you're looking for an exception to the terms. © 2020–2023, Trail of Bits.

graphtage's People

Contributors

artemdinaburg avatar bollwyvl avatar c00k133 avatar dependabot[bot] avatar ehershey avatar esultanik avatar loic5 avatar oldsj avatar woodruffw avatar zombienub avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphtage's Issues

Consider additional dependencies for performance, security

Thanks again for graphtage!

While I haven't used XML diffing in anger yet, it would be interesting to explore some (optional) dependencies to increase the robustness and performance of that component:

  • lxml has the same API, but better performance, than stdlib
  • defusedxml helps prevent well-known malicious XML attacks that works with stdlib or lxml

Similarly, a number of far-higher performance JSON parsers are available, with different ease-of-installation/speed/memory tradeoffs for which it might be hard to anticipate user preference:

If there is interest, I could probably take a stab at a PR for this:

  • change the json API to accept an optional parser
    • add extras with a sensible bottom version pins
  • change the xml API to accept an optional parser
    • add defusedxml in install_requires
    • add lxml in an extras section
      • or install_requires, as "complexity of installation" is no longer really a concern once scipy enters the picture...
  • test against different combinations with tox in CI

ValueError: Unsupported Python object None of type <class 'NoneType'>

$ cat null.json
null
$ graphtage null.json null.json
Traceback (most recent call last):
  File "/sbin/graphtage", line 8, in <module>
    sys.exit(main())
  File "/usr/lib/python3.8/site-packages/graphtage/__main__.py", line 286, in main
    from_tree = from_format.build_tree_handling_errors(from_path, options)
  File "/usr/lib/python3.8/site-packages/graphtage/json.py", line 254, in build_tree_handling_errors
    return self.build_tree(path=path, options=options)
  File "/usr/lib/python3.8/site-packages/graphtage/json.py", line 250, in build_tree
    return build_tree(json.load(f), options)
  File "/usr/lib/python3.8/site-packages/graphtage/json.py", line 70, in build_tree
    raise ValueError(f"Unsupported Python object {python_obj!r} of type {type(python_obj)}")
ValueError: Unsupported Python object None of type <class 'NoneType'>

The same happens with JSON files like [null] and {"a": null}. Version is 0.2.1.

Utilizing graphtage for conversion

Typical use case of graphtage is:

A file on Left Hand side (LHS) - A file on Right Hand side (RHS) = diffs

Question:
Given a LHS file, can one use the API to create a diff class object and apply that to LHS and create a new document?

Database structure evolution comparison

Hi,
First I wanted to say that your work is very impressive and I feel could be applied in many different ways!
As you are soliciting possible use cases for this toolset/technology, would a valid use in the database realm be:
Doing a diff between two db schemas and providing the sequential list of edits that will bring you from the origin version to the new version (syncing)? The db schema could be represented as a tree encapsulating the relationship among columns, constraints, tables, indexes, etc.
So for example if a column were to get dropped and that column were referenced as a foreign key constraint to another table as well as being included in an index, the diff would be represented as the series of drops/adds/alters that would enable the edits to be applied to version a sequentially yielding b.

My particular use case is for Oracle DB schema evolution and although there are some costly commercial tools out there, they utilize Oracle specific features in order to accomplish the sync. There don't appear to be any tools that do this type of sync utilizing the approach you have taken with Graphtage that could be applicable across multiple databases. Below are a couple of links describing some of the approaches and the various challenges with schema evolution.

Schema Evolution Research 1
Schema Evolution Research 2
Schema Evolution Research 3

I would be very interested to hear your thoughts on the applicability of this use case to your work.

Regards,
Chris Whelan

kubectl diff

The diff in Kubectl can be altered with KUBECTL_EXTERNAL_DIFF here is the ref

These options do all work:

  • KUBECTL_EXTERNAL_DIFF="colordiff -N -u"
  • KUBECTL_EXTERNAL_DIFF="dyff between --omit-header --set-exit-code"
  • KUBECTL_EXTERNAL_DIFF='diff -qr'

I can't, however, make it work with graphtage using the following config

KUBECTL_EXTERNAL_DIFF="graphtage --from-yaml --to-yaml --debug " kubectl diff -f ./dist/aws/cert-manager.k8s.yaml

Traceback (most recent call last):
  File "/Users/vadim/.local/bin/graphtage", line 8, in <module>
    sys.exit(main())
  File "/Users/vadim/.local/lib/python3.10/site-packages/graphtage/__main__.py", line 323, in main
    from_tree = from_format.build_tree_handling_errors(from_path, options)
  File "/Users/vadim/.local/lib/python3.10/site-packages/graphtage/yaml.py", line 236, in build_tree_handling_errors
    return self.build_tree(path=path, options=options)
  File "/Users/vadim/.local/lib/python3.10/site-packages/graphtage/yaml.py", line 228, in build_tree
    tree = build_tree(path=path, options=options)
  File "/Users/vadim/.local/lib/python3.10/site-packages/graphtage/yaml.py", line 23, in build_tree
    with open(path, 'rb') as stream:
IsADirectoryError: [Errno 21] Is a directory: '/var/folders/v5/27sfclt13g54_qgh9kmkqf6w0000gn/T/LIVE-3245526907'

How could I accomplish that with graphtage?

Infinite looping in `repeat_until_tightened` when using `pydiff.diff`

Hi! Thanks for creating this library!
I've been experimenting with it a bit today. It's pretty awesome.

I noticed that sometimes pydiff.diff gets stuck into an infinite loop.
I stepped through the code a bit and it's stuck in repeat_until_tightened, with bounds that stay the same ([0, 18]) and don't become "definitive". I don't understand the algorithms (yet), so I wasn't sure what the problem is beyond this.

Here's the smallest repro case I could come up with:

import dataclasses
import graphtage


@dataclasses.dataclass
class Thing:
    foo: str


def main() -> None:
    d = graphtage.pydiff.diff([Thing("ok")], [Thing("bad")])

    # Interestingly, this runs fine:
    # d = graphtage.pydiff.diff(Thing("ok"), Thing("bad"))

    with graphtage.printer.DEFAULT_PRINTER as printer:
        graphtage.pydiff.PyDiffFormatter.DEFAULT_INSTANCE.print(printer, d)


if __name__ == "__main__":
    main()

Let me know if there's anything I can help to debug this!

Fails to match closing HTML tags

Graphtage currently throws an error when encountering a closing tag such as

</head>

because it fails to match the tag appropriately, preventing it from diffing HTML.

Option to only a digest with just the paths to the changes and what changed

When diffing huge files with large maps instead of reading through the whole file it would be great to get a list with the path and what changed such as:

web->javascript->api->abortSignal->chrome                false->"100.0"
web->javascript->api->[sreviceWorker->serviceWorker]     no value changes

so at a glace I can see that the right things changed

I don't know of any tool that does it already nor, any other tool that builds up the internal data structures so it could make such a list.

Results from comparing XML could be better

Reporting on behalf of a user on Twitter:

Two identical XML files will incorrectly output a ton of text

# graphtage -v
Graphtage version 0.2.1
# keepassxc-cli export ~/Sync/Passwords-20200612_15-09-57.kdbx > 20200612_15-09-57.xml
# keepassxc-cli export ~/Sync/EstatePasswords-20200502_17-26-13.kdbx > 20200502_17-26-13.xml
# graphtage 20200502_17-26-13.xml 20200612_15-09-57.xml
... (lots of colored output)
# diff 20200502_17-26-13.xml 20200612_15-09-57.xml
... (no output because the files are identical)
# head -1 20200502_17-26-13.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

Here's a simple reproducer:

# cat 2.xml 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<KeePassFile>
<Meta>
</Meta>
</KeePassFile>
# cp 2.xml 1.xml
# graphtage 1.xml 2.xml
... (it spits out the full content in green and black of the entire file except for the XML header)

Compare of two simple XML files with an attribute goes into seemingly infinite loop

Hello,

I wanted to test utilizing graphtage to compare XML files and created the simple XML structure as shown below. Running the compare with only a single attribute on an element with a different attribute value caused the apparent loop issue you can see in the output below. (It got stuck at 35%)

Platform MacOS High Sierra 10.13.6
Python 3.8.5
Graphtage Version 0.2.1

Regards,
Chris Whelan

ChrisMBP:xmltest cwhelan$ cat one.xml

<root>
  <parent>
	<child1 attribute1="foo">child1</child1>
        <child2>child2</child2>
  </parent>
</root>

ChrisMBP:xmltest cwhelan$ cat two.xml

<root>
  <parent>
	<child1 attribute1="bar">child1</child1>
        <child2>child2</child2>
  </parent>
</root>

ChrisMBP:xmltest cwhelan$ graphtage one.xml two.xml -e
WARNING:graphtage.sequences:The most recent call to tighten_bounds() on edit <graphtage.xml.XMLElementEdit object at 0x11a9f4190> tightened its bounds from [29, 84] to [6, 6]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x110ac5430> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x11a9f4100> returned bounds [6, 6] when the previous bounds were [29, 84]
...

Disregard Document Position in File

Hi,

Is there any option to tell it to treat the same document in two different files as identical, even if it is positioned differently in the two files? For example, I have rules.yaml that looks like this:

# cat /tmp/rules.yaml
- macro: never_true
  condition: (evt.num=0)

- macro: always_true
  condition: (evt.num>=0)

- macro: spawned_process
  condition: evt.type in (execve, execveat) and evt.dir=<

- rule: ls run
  desc: ls run
  condition: spawned_process and proc.name=ls
  output: ls run
  priority: INFO
  tags: [process]

while also having rules2.yaml that is the same but one of the documents is located in a different location:

# cat /tmp/rules2.yaml
- macro: never_true
  condition: (evt.num=0)

- macro: always_true
  condition: (evt.num>=0)

- rule: ls run
  desc: ls run
  condition: spawned_process and proc.name=ls
  output: ls run
  priority: INFO
  tags: [process]

- macro: spawned_process
  condition: evt.type in (execve, execveat) and evt.dir=<

When running graphtage, it shows the following:

$ graphtage /tmp/rules.yaml /tmp/rules2.yaml

- condition: (evt.num=0)
  macro: never_true
- condition: (evt.num>=0)
  macro: always_true
- c̶o̶n̶d̶i̶t̶i̶o̶n̶:̶ ̶e̶v̶t̶.̶t̶y̶p̶e̶ ̶i̶n̶ ̶(̶e̶x̶e̶c̶v̶e̶,̶ ̶e̶x̶e̶c̶v̶e̶a̶t̶)̶ ̶a̶n̶d̶ ̶e̶v̶t̶.̶d̶i̶r̶=̶<̶
  m̶a̶c̶r̶o̶:̶ ̶s̶p̶a̶w̶n̶e̶d̶_̶p̶r̶o̶c̶e̶s̶s̶
- condition: spawned_process and proc.name=ls
  desc: ls run
  output: ls run
  priority: INFO
  rule: ls run
  tags:
  - process
- c̟o̟n̟d̟i̟t̟i̟o̟n̟:̟ ̟e̟v̟t̟.̟t̟y̟p̟e̟ ̟i̟n̟ ̟(̟e̟x̟e̟c̟v̟e̟,̟ ̟e̟x̟e̟c̟v̟e̟a̟t̟)̟ ̟a̟n̟d̟ ̟e̟v̟t̟.̟d̟i̟r̟=̟<̟
  m̟a̟c̟r̟o̟:̟ ̟s̟p̟a̟w̟n̟e̟d̟_̟p̟r̟o̟c̟e̟s̟s̟

which tells me that they are different. Is there a way to tell it to ignore these types of differences (in this case, it would tell me the two files are identical)? Thanks

Add Homebrew support

Would it be possible to add Homebrew support? This would improve machine automation and setup by easily being able to install this tool.

Expects quoted attributes in HTML unnecessarily, preventing diffing

When trying to diff an HTML file, Graphtage throws an error when encountering e.g.:

<meta name=foo

because it expects quoted attributes like so:

<meta name="foo"

However, the first variant without quotes is perfectly valid HTML and should not prevent Graphtage from diffing the file.

Investigate approximate matching

Allow the user to specify a given epsilon of matching cost, and find a matching that is at most that epsilon from the cost of the optimal matching.

Option to remove the plusses from the output?

It seems the diff output uses both the green highlighting, and the "plus" formatting to indicate an addition. It would be lovely if we could keep the highlighting and remove the plusses on each character, or vice-versa. In my case, my downstream processing of the data (converting to HTML and LaTeX) seems to have difficulty with these characters. Similarly for the deletions.

I would be happy if we could --no-unicode-formatting or similar, indicating that we keep the ANSI colour codes.

pydiff builds an incorrect tree for embedded tuples and `None`

Discovered by @BradSwain.

print_diff(None, {'a': (1,2)}) gives the following error:

ValueError: Error while setting StringNode('tuple').parent = /* ..bunch of stuff here ...*/
Parent is already assigned to <graphtage.pydiff.PyObj object at 0x2c13a1f90>

There appears to be a discrepancy in the output of pydiff.build_treefor a tuple and a tuple in a dict.
The first is a ListNode, but nested in a dict it shows up as a PyObj

In [2]: build_tree((1,2))
Out[2]: ListNode((IntegerNode(1), IntegerNode(2)))
In [3]: build_tree({'a': (1,2)})
Out[3]: DictNode([KeyValuePairNode(key=StringNode('a'), value=<graphtage.pydiff.PyObj object at 0x2ba462c50>)])

Challenge getting delta from two document change allowing split/merge/move text inside json nodes

Hello community,

I'm trying to find a way to compute delta on a json tree with the minimal size possible (so with the ability to split/move/match nodes)

I first tried to implement an algorithm from scratch using the slate operations that I gather each time the editor got an update and try to optimize them in a way to get only the relevant operations at the end. It is pretty easy to combine/merge text operations, but when you come to nodes operations, the task become a real nightmare.

I first get to know google diff-match-patch for plain text that works well on planar data to find out what has been moved or replaced, but like explained it do not work well for structured data.
Continuing the research by looking json diffing libraries, but you are facing libraries that do not try to find moving/splitting nodes and results with remove everything and insert everything.
Then you can find interesting work made on structured data with the homologous format XML and understand you are facing a NP-hard problem with a lot of academic research on the subject and lot of different libs with pros and cons (XMLDiff, XyDiff, graphtage, ...).

My issue I do not found yet a library that express my need and make simple changes that could be displayed as redlining.

Simple json example from a document tree
const initial = [
  {
    "type": "p",
    "children": [
      {
        "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin "
      },
      {
        "text": "efficitur",
        "bold": true
      },
      {
        "text": " sit amet sem a feugiat. Sed finibus eleifend elit a ultrices. Curabitur ac massa at mauris mollis varius."
      }
    ]
  }
]

const final = [
  {
    "type": "p",
    "children": [
      {
        "text": "Lorem ipsum dolor sit "
      },
      {
        "text": "amet",
        "bold": true
      },
      {
        "text": ", consectetur Hello World adipiscing elit. Proin "
      },
      {
        "text": "efficitur",
        "bold": true
      },
      {
        "text": " sit amet sem. Sed finibus "
      },
      {
        "text": "eleifend",
        "underline": true
      },
      {
        "text": " elit a ultrices. Curabitur ac massa at mauris mollis varius."
      }
    ]
  }
]

// Resulting deltas
const deltas = [
  { "op": "split", "path": [0, 0], "position": 26 },
  { "op": "split", "path": [0, 0], "position": 22 },
  { "op": "addProps", "path": [0, 1], "key": "bold", "value": true }
  ...
]
XML transposed of the json version
# initial
<document><node type="p"><text>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin </text><text bold="true">efficitur</text><text> sit amet sem a feugiat. Sed finibus eleifend elit a ultrices. Curabitur ac massa at mauris mollis varius.</text></node></document>

# final
<document><node type="p"><text>Lorem ipsum dolor sit </text><text bold="true">amet</text><text>, consectetur Hello World adipiscing elit. Proin </text><text bold="true">efficitur</text><text> sit amet sem. Sed finibus </text><text underline="true">eleifend</text><text> elit a ultrices. Curabitur ac massa at mauris mollis varius.</text></node></document>
Results when using XyDiff is replace everything (very old library)
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<xy:unit_delta xmlns:xy="urn:schemas-xydiff:xydelta">
  <xy:t fromXidMap="(9-14;3-4;15-20;7-8|21)">
    <xy:d par="7" pos="3" xm="(5-6)">
      <text> sit amet sem a feugiat. Sed finibus eleifend elit a ultrices. Curabitur ac massa at mauris mollis varius.</text>
    </xy:d>
    <xy:d par="7" pos="1" xm="(1-2)">
      <text>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin </text>
    </xy:d>
    <xy:i par="7" pos="1" xm="(9-10)">
      <text>Lorem ipsum dolor sit </text>
    </xy:i>
    <xy:i par="7" pos="2" xm="(11-12)">
      <text bold="true">amet</text>
    </xy:i>
    <xy:i par="7" pos="3" xm="(13-14)">
      <text>, consectetur Hello World adipiscing elit. Proin </text>
    </xy:i>
    <xy:i par="7" pos="5" xm="(15-16)">
      <text> sit amet sem. Sed finibus </text>
    </xy:i>
    <xy:i par="7" pos="6" xm="(17-18)">
      <text underline="true">eleifend</text>
    </xy:i>
    <xy:i par="7" pos="7" xm="(19-20)">
      <text> elit a ultrices. Curabitur ac massa at mauris mollis varius.</text>
    </xy:i>
  </xy:t>
</xy:unit_delta>

Results when using graphtage (both json & xml version is looping infinitely):

...
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x7f5756c38790> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x7f5730e519d0> returned bounds [191, 191] when the previous bounds were [212, 457]
WARNING:graphtage.bounds:The most recent call to <function FixedLengthSequenceEdit.tighten_bounds at 0x7f5756c38790> on <graphtage.sequences.FixedLengthSequenceEdit object at 0x7f5730e519d0> returned bounds [191, 191] when the previous bounds were [212, 457]
Diffing:  31%|███████████████████████████████████████████████████▊                                                                                                                  | 111/356 [00:02<00:04, 156.74it/s]
But it works when using another sample
# initial
<catalog>
  <product type="A">
    <status>Available</status>
    <name>Ipod Mp3 Player</name>
    <description>10G HD – Windows</description>
    <price>$450</price>
  </product>
  <product>
    <status>Not available</status>
    <name>Digital Camera</name>
    <description>Canon Ixus II</description>
  </product>
</catalog> 

# final
<catalog>
  <product type="B">
    <status>Available</status>
    <name>Ipod Mp3</name>
    <truc>Player</truc>
    <description>10G HD – Windows</description>
    <price>$460</price>
  </product>
  <product>
    <status>Available</status>
    <name>Digital Camera</name>
    <description>Canon Ixus II</description>
    <price>$300</price>
  </product>
</catalog> 

# delta
<catalog>                                                                                                                                                                                                             
  <product type="̶A̶"̶ -> "̟B̟"̟>                                                                                                                                                                                           
    <status>Available</status>                                                                                                                                                                                        
        <name>Ipod Mp3 ̶P̶l̶a̶y̶e̶r̶</name>
        <̟t̟r̟u̟c̟>̟P̟l̟a̟y̟e̟r̟<̟/̟t̟r̟u̟c̟>̟
        <description>10G HD – Windows</description>
        <price>$46̟5̶0</price>
    </product>
    <product>
    <status>A̟N̶o̶t̶ ̶a̶vailable</status>
        <name>Digital Camera</name>
        <description>Canon Ixus II</description>
        <̟p̟r̟i̟c̟e̟>̟$̟3̟0̟0̟<̟/̟p̟r̟i̟c̟e̟>̟
    </product>
</catalog>

I'm wondering how can I improve the results of the diffing? What if I'm preprocessing the data in a way? Is there other libraries with a better suitable algorithm?
At the end I found this topic related to many amount of studies and academic research but do not find anything suiting my case.

I would enjoy getting some help to figuring out this complex challenge.

ValueError on simple JSON comparison with `-k`

a.json:

{"b": true}

b.json:

{"test": "hi"}
$ graphtage a.json b.json
{
    "++test++~~b~~": true -> "hi"
}
$ graphtage a.json b.json -k
Traceback (most recent call last):

ValueError: -∞ + ∞ is undefined

Using as git differ

Has anyone tried adding this to git as it's differ yet? If so, instructions on doing that would be really useful!

Best approach to use graphtage to create a "diff" of an already existing tree?

Hey! Sorry for the broad scope of this question, but I'm having some trouble wrapping my head around how to use this library to generate a "diff" or "patch" for an already existing tree structure.

Background

We're writing a specification, and want to highlight changes between versions of the specification. Currently we use sphinx and a bunch of custom tooling to render the documents. You can see what the current documentation looks like here.

We've hit a few walls with this approach and have decided to move to a custom solution. You can see what that looks like over here.

The new tooling, docc, represents each document as a tree of nodes. This is what we want to calculate a diff between. For example, this is how we represent Python types.

Goal

I'd like to take two document trees, perform some magic with graphtage, and get out a third tree representing what's changed. Here's a really simple example:

Before After Output
graph TD;
    A-->B
    A-->C
graph TD;
    A-->B
    A-->D
graph TD;
    A-->B
    A-->Diff
    Diff-->|removed| C
    Diff-->|added| D

Issues

I've tried the Diffing In-Memory Python Objects approach, but received a utf-8 decoding error.

I've tried subclassing LeafNode and ContainerNode, but I'm not familiar enough with graphtage to implement them correctly.

Current Approach

My current approach is to map my tree objects into FixedKeyDictNode instances, then back into my tree objects. Now I'm stuck figuring out how to convert the EditedTreeNode instances into the Diff(before, after) style node from the above example. What would you suggest?

Switch to `pyproject.toml`

We don't do anything too fancy in the setup.py here, so we could switch over without too much pain (with flit as the build backend.)

ImportError: cannot import name 'runtime_checkable' from 'typing_extensions'

Win10, Python 3.7, after

pip3 install graphtage (went without any issues):

PS U:\> graphtage
Traceback (most recent call last):
  File "d:\_bin\miniconda\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "d:\_bin\miniconda\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "D:\_bin\Miniconda\Scripts\graphtage.exe\__main__.py", line 4, in <module>
  File "d:\_bin\miniconda\lib\site-packages\graphtage\__init__.py", line 1, in <module>
    from . import graphtage
  File "d:\_bin\miniconda\lib\site-packages\graphtage\graphtage.py", line 8, in <module>
    from .edits import AbstractEdit, EditCollection
  File "d:\_bin\miniconda\lib\site-packages\graphtage\edits.py", line 8, in <module>
    from .tree import CompoundEdit, Edit, EditedTreeNode, GraphtageFormatter, TreeNode
  File "d:\_bin\miniconda\lib\site-packages\graphtage\tree.py", line 7, in <module>
    from typing_extensions import Protocol, runtime_checkable
ImportError: cannot import name 'runtime_checkable' from 'typing_extensions' (d:\_bin\miniconda\lib\site-packages\typing_extensions.py)
typing                            3.6.6
typing-extensions                 3.6.6

Chosen colourscheme is sometimes unreadable

If the terminal is using lighter shades of green or red, graphtage's change output can be hard to read because it outputs white text on top.

image

A better default might be to output black text in those parts of the output. Ideally, this would be configurable.

Text missing from HTML diff

When using the following test HTML files as input...

$ cat old.html
<html>
        <body>
                some <div>text and more</div> text
        </body>
</html>

$ cat new.html
<html>
        <body>
                some <div class='red'>text</div> and more <strong>text</strong>
        </body>
</html>

$ graphtage old.html new.html
<html>
        <body>
                some <̟d̟i̟v̟ ̟c̟l̟a̟s̟s̟=̟"̟r̟e̟d̟"̟>̟t̟e̟x̟t̟<̟/̟d̟i̟v̟>̟
        <̟s̟t̟r̟o̟n̟g̟>̟t̟e̟x̟t̟<̟/̟s̟t̟r̟o̟n̟g̟>̟
        <̶d̶i̶v̶>̶t̶e̶x̶t̶ ̶a̶n̶d̶ ̶m̶o̶r̶e̶<̶/̶d̶i̶v̶>̶
    </body>
</html>

+ screenshot:
image

..., as you can see, the text and more is missing from the diff generated by graphtage.

I've tried some other diff tools and it seems and none of them had any success with correctly processing these two files for some reason (many are using the same core algorithm I suppose). Is there some kind of general issue with processing text not enclosed in tags (as in, and more is between two elements, but not enclosed in any tag (apart from the parent <body> tag) itself)?

I have also tried surrounding and more in a <p> tag in new.html, which resulted in this mess:

$ graphtage old.html new.html
<html>
        <body>
                some <̟d̟i̟v̟ ̟c̟l̟a̟s̟s̟=̟"̟r̟e̟d̟"̟>̟t̟e̟x̟t̟<̟/̟d̟i̟v̟>̟
        <p̟d̶i̶v̶>t̶e̶x̶t̶ ̶and more</p̟d̶i̶v̶>
        <̟s̟t̟r̟o̟n̟g̟>̟t̟e̟x̟t̟<̟/̟s̟t̟r̟o̟n̟g̟>̟
    </body>
</html>

+ screenshot:
image

What's happening?

Feature Request: JSONPatch output

JSONPatch is a format for submitting machine usable but still marginally human readable partial record updates, usually over the HTTP PATCH method. While I've always been interested in using it to accept updates via an api, the usual problem is while there are any number of libraries that can take the patch and apply it to an existing record, the opposite, taking two records and generating the patch, doesn't seem to exist (at least as of my last search). Graphtage looks like it might be well suited to doing so and would be a nice selling point for it.

Option to not consider list edits

Add an option to not consider list removals and insertions. Add another option to do the same, but only if the lists have the same length.

Error parsing example.csv: Expecting value: line 1, column 1 (char 0)

Trying to process the following csv, which is taken from https://www.ibm.com/docs/en/elm/7.0.3?topic=files-csv-file-format-examples

Artifact Type, Primary Text, Name, Description, Owner
MyRequirementType, "The vehicle must have two wheels.", "Vehicle wheels", "This requirement defines the rules for vehicles", "Joe Blogs"

When I execute the following:
graphtage --from-csv --to-json example.csv example.csv

I get:

Error parsing example.csv: Expecting value: line 1, column 1 (char 0)

Is that an invalid csv?

I am using Graphtage version 0.2.6

TypeError: Cannot create a consistent method resolution

Under Python 3.9, I get the following error when running any graphtage command:

Traceback (most recent call last):
  File "/media/michael/Storage2/Programming/CWLDiff/venv/bin/graphtage", line 5, in <module>
    from graphtage.__main__ import main
  File "/media/michael/Storage2/Programming/CWLDiff/venv/lib/python3.9/site-packages/graphtage/__init__.py", line 1, in <module>
    from . import graphtage
  File "/media/michael/Storage2/Programming/CWLDiff/venv/lib/python3.9/site-packages/graphtage/graphtage.py", line 11, in <module>
    from .multiset import MultiSetEdit
  File "/media/michael/Storage2/Programming/CWLDiff/venv/lib/python3.9/site-packages/graphtage/multiset.py", line 12, in <module>
    from .matching import WeightedBipartiteMatcher
  File "/media/michael/Storage2/Programming/CWLDiff/venv/lib/python3.9/site-packages/graphtage/matching.py", line 263, in <module>
    class PathSet(Generic[T], Matching[T]):
  File "/usr/lib/python3.9/abc.py", line 85, in __new__
    cls = super().__new__(mcls, name, bases, namespace, **kwargs)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases Generic, Matching

Under Python 3.8 this doesn't seem to exist.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.