Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New features in version 0.1.0 #2

Closed
9 tasks done
HansBug opened this issue Aug 7, 2021 · 10 comments
Closed
9 tasks done

New features in version 0.1.0 #2

HansBug opened this issue Aug 7, 2021 · 10 comments
Assignees

Comments

@HansBug
Copy link
Member

HansBug commented Aug 7, 2021

Implemented in #5 .

  • Dump of the tree value graph.
  • Suport pickle.dumps of TreeValue objects
  • Binary-based full data dump
  • Binary-based full data load
  • Native-python-based full data load
  • Self calculation with original address
  • Self operator with original address
  • Add more features in general_treevalue, such as NotImplement
  • CLI support (dump/load, graph generation, graphviz code dump, etc)
@HansBug
Copy link
Member Author

HansBug commented Aug 7, 2021

@HansBug
Copy link
Member Author

HansBug commented Aug 10, 2021

@HansBug
Copy link
Member Author

HansBug commented Aug 10, 2021

Task 2: Dump of the tree value graph.

import pickle

t = FastTreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})
binary = picke.dumps(t)  # dump to binary
tx = pickle.loads(binary)  # load from binary
assert t == tx

@HansBug HansBug mentioned this issue Aug 10, 2021
9 tasks
@HansBug
Copy link
Member Author

HansBug commented Aug 10, 2021

@HansBug
Copy link
Member Author

HansBug commented Aug 11, 2021

Task 3 & 4: Dump and load to binary

from treevalue import dump, load, FastTreeValue

t = FastTreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})

with open('dump_file.btv', 'wb') as file:
    dump(t, file=file)  # dump data to file without treevalue's type. Not the same as pickle.dump

with open('dump_file.btv', 'rb') as file:
    t1 = load(file=file, type_=FastTreeValue)  # type_ is necessary when loaded

assert t1 == t

@HansBug
Copy link
Member Author

HansBug commented Aug 11, 2021

Task 7: Self operator with original address

from treevalue import FastTreeValue

t = FastTreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})
t2 = FastTreeValue({'a': 11, 'b': 20, 'x': {'c': 33, 'd': 48}})

if __name__ == '__main__':
    print('t:')
    print(t)

    print('t2:')
    print(t2)

    t += t2
    print('t += t2:')
    print(t)

Output should be

t:
<FastTreeValue 0x7f8195cb9b50 keys: ['a', 'b', 'x']>
├── 'a' --> 1
├── 'b' --> 2
└── 'x' --> <FastTreeValue 0x7f8195cb9910 keys: ['c', 'd']>
    ├── 'c' --> 3
    └── 'd' --> 4

t2:
<FastTreeValue 0x7f819275af50 keys: ['a', 'b', 'x']>
├── 'a' --> 11
├── 'b' --> 20
└── 'x' --> <FastTreeValue 0x7f8193ae1950 keys: ['c', 'd']>
    ├── 'c' --> 33
    └── 'd' --> 48

t += t2:
<FastTreeValue 0x7f8195cb9b50 keys: ['a', 'b', 'x']>
├── 'a' --> 12
├── 'b' --> 22
└── 'x' --> <FastTreeValue 0x7f8195cb9910 keys: ['c', 'd']>
    ├── 'c' --> 36
    └── 'd' --> 52

In the previous version, the self-added t will not keep the same address.

@HansBug
Copy link
Member Author

HansBug commented Aug 11, 2021

Task 6: Self calculation with original address

from treevalue import FastTreeValue, method_treelize


class MyTreeValue(FastTreeValue):
    @method_treelize(self_copy=True)  # Enable of self_copy argument will make the method be a self calculation
    def append(self, x):
        return self + x


t = MyTreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})
t2 = MyTreeValue({'a': 11, 'b': 20, 'x': {'c': 33, 'd': 48}})

if __name__ == '__main__':
    print('t:')
    print(t)

    print('t2:')
    print(t2)

    rt = t.append(t2)
    print('t after t.append(t2):')
    print(t)
    assert rt is t  # rt is t, chain calling is supported, such as t.append(xxx).append(yyy)

Output should be

t:
<MyTreeValue 0x7f9abe6e2a90 keys: ['a', 'b', 'x']>
├── 'a' --> 1
├── 'b' --> 2
└── 'x' --> <MyTreeValue 0x7f9abe6ec550 keys: ['c', 'd']>
    ├── 'c' --> 3
    └── 'd' --> 4

t2:
<MyTreeValue 0x7f9abd3b2490 keys: ['a', 'b', 'x']>
├── 'a' --> 11
├── 'b' --> 20
└── 'x' --> <MyTreeValue 0x7f9abd3b2950 keys: ['c', 'd']>
    ├── 'c' --> 33
    └── 'd' --> 48

t after t.append(t2):
<MyTreeValue 0x7f9abe6e2a90 keys: ['a', 'b', 'x']>
├── 'a' --> 12
├── 'b' --> 22
└── 'x' --> <MyTreeValue 0x7f9abe6ec550 keys: ['c', 'd']>
    ├── 'c' --> 36
    └── 'd' --> 52

@HansBug
Copy link
Member Author

HansBug commented Aug 11, 2021

Task 8: Add more features in general_treevalue, such as NotImplement

An example of extension for __add__ and __radd__ function.

from treevalue import general_tree_value


class NonDefaultTreeNumber(general_tree_value(base=dict(), methods=dict(
    __add__=dict(missing=0, mode='outer'),
    __radd__=dict(missing=0, mode='outer'),
    __iadd__=dict(missing=0, mode='outer')
))):
    pass


t = NonDefaultTreeNumber({'a': 1, 'b': 2, 'x': {'c': 3, 'e': 9}})
t2 = NonDefaultTreeNumber({'b': 21, 'd': 18, 'x': {'c': 3}, 'y': {'t': 4}})

if __name__ == '__main__':
    print('t + t2:')
    print(t + t2)

The result should be

t + t2:
<NonDefaultTreeNumber 0x7f396c7d5910 keys: ['a', 'b', 'd', 'x', 'y']>
├── 'a' --> 1
├── 'b' --> 23
├── 'd' --> 18
├── 'x' --> <NonDefaultTreeNumber 0x7f3969c5c610 keys: ['c', 'e']>
│   ├── 'c' --> 6
│   └── 'e' --> 9
└── 'y' --> <NonDefaultTreeNumber 0x7f3969cbc290 keys: ['t']>
    └── 't' --> 4

Convenient, isn't it?

Another example of disabling/modifying some of the functions or operators.

import sys

from treevalue import general_tree_value
from treevalue.utils import str_traceback


class BanAndOverrideTreeNumber(general_tree_value(methods=dict(
    __add__=NotImplemented,
    __radd__=NotImplemented,
    __iadd__=NotImplemented,
    __mul__=KeyError("lksdjfkl"),
    __rmul__=KeyError("lsdfjkldks"),
    __imul__=KeyError("dklfgjsl"),
    __matmul__=KeyError,
    __rmatmul__=KeyError,
    __imatmul__=KeyError,
    __pos__=(lambda sp: sp // 2),
    __truediv__=(lambda sp: sp - 2),
))):
    pass


# the structure of t and t2 are exactly the same
t = BanAndOverrideTreeNumber({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 9}})
t2 = BanAndOverrideTreeNumber({'a': 21, 'b': 18, 'x': {'c': 3, 'd': 4}})

if __name__ == '__main__':
    try:
        print('t + t2:')
        print(t + t2)
    except Exception as err:  # __add__ is banned on operators' level
        print(str_traceback(err), file=sys.stderr)

    try:
        print('t * t2:')
        print(t * t2)
    except Exception as err:  # raise KeyError when __mul__ is called
        print(str_traceback(err), file=sys.stderr)

    print('+t:')
    print(+t)  # __pos__ is modified

    print('t / 2:')
    print(t / 2)  # __truediv__ is modified

The output (including stdout and stderr) is

t + t2:
Traceback (most recent call last):
  File "test_fxxk.py", line 30, in <module>
    print(t + t2)
TypeError: unsupported operand type(s) for +: 'BanAndOverrideTreeNumber' and 'BanAndOverrideTreeNumber'

t * t2:
Traceback (most recent call last):
  File "test_fxxk.py", line 36, in <module>
    print(t * t2)
  File "/home/hansbug/pyprojects/treevalue/treevalue/utils/func.py", line 176, in _new_func
    return processor(_result)
  File "/home/hansbug/pyprojects/treevalue/treevalue/utils/func.py", line 85, in _new_func
    return func(*_get_args(*args), **_get_kwargs(**kwargs))
  File "/home/hansbug/pyprojects/treevalue/treevalue/utils/func.py", line 189, in _post_for_raising
    raise ret
KeyError: 'lksdjfkl'

+t:
<BanAndOverrideTreeNumber 0x7f9529c26a90 keys: ['a', 'b', 'x']>
├── 'a' --> 0
├── 'b' --> 1
└── 'x' --> <BanAndOverrideTreeNumber 0x7f9529c2ae90 keys: ['c', 'd']>
    ├── 'c' --> 1
    └── 'd' --> 4

t / 2:
<BanAndOverrideTreeNumber 0x7f9529c3b490 keys: ['a', 'b', 'x']>
├── 'a' --> -1
├── 'b' --> 0
└── 'x' --> <BanAndOverrideTreeNumber 0x7f9529c3bc50 keys: ['c', 'd']>
    ├── 'c' --> 1
    └── 'd' --> 7

@HansBug
Copy link
Member Author

HansBug commented Aug 11, 2021

Task 5 & 9: Cli Support, tree dump and graph drawing

Example of graph drawing via cli: https://opendilab.github.io/treevalue/5/merge/tutorials/quick_start/index.html

Example of dump binary data of tree value (demo.py is the same as that int the demo above):

treevalue export -t 'demo.*'

The listdir after this command

hansbug@hansbug-VirtualBox:~/ttt$ ls -l
总用量 20
-rw-rw-r-- 1 hansbug hansbug  357 8月  11 08:44 demo.py
drwxrwxr-x 2 hansbug hansbug 4096 8月  11 08:44 __pycache__
-rw-rw-r-- 1 hansbug hansbug  208 8月  11 08:44 t1.btv
-rw-rw-r-- 1 hansbug hansbug  211 8月  11 08:44 t2.btv
-rw-rw-r-- 1 hansbug hansbug  299 8月  11 08:44 t3.btv

And the 33 btv files can be loaded by treevalue.load, like this

from treevalue import load, FastTreeValue

if __name__ == '__main__':
    with open('t1.btv', 'rb') as file:
        t = load(file, type_=FastTreeValue)

    print(t)

The output of loaded t:

<FastTreeValue 0x7eff8fa49e90 keys: ['a', 'b', 'x']>
├── 'a' --> 's1'
├── 'b' --> 2
└── 'x' --> <FastTreeValue 0x7eff8fa49bd0 keys: ['c', 'd']>
    ├── 'c' --> 3
    └── 'd' --> [1, 2]

@HansBug HansBug assigned HansBug and PaParaZz1 and unassigned HansBug Aug 11, 2021
HansBug added a commit that referenced this issue Sep 4, 2021
Development for the issue #2 and issue #4
@HansBug
Copy link
Member Author

HansBug commented Sep 4, 2021

Pull request #5 has been merged.

@HansBug HansBug closed this as completed Sep 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants