Quick Start

After the installation is complete, we can run some simple examples. This page will show you this.

Simple Translation

A simplest translation can be processed with the code below.

1
2
3
4
5
6
7
8
9
from potc import transobj

if __name__ == '__main__':
    print("transobj(1):", transobj(1))
    print("transobj([1, 2, 'sdkfj\u0123']):",
          transobj([1, 2, 'sdkfj\u0123']))

    print('empty set:', transobj(set()))
    print('1-lengthened tuple:', transobj((1,)))

The output result should be

1
2
3
4
transobj(1): 1
transobj([1, 2, 'sdkfjģ']): [1, 2, 'sdkfjģ']
empty set: set()
1-lengthened tuple: (1, )

Most of the primitive data types supported by python can be turned back to runnable source code with potc.

Scriptable Translation

If we need to translate multiple values, and dump the translation result to a runnable .py script, we can do like this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import math
from typing import Callable, Dict, List

import numpy as np

from potc import transvars

if __name__ == '__main__':
    _code = transvars({
        'complex_array': [
            1, 1.5, math.e, object(),
            float('nan'), float('+inf'), float('-inf'),
            'str', None, {1, 2, 't' * 30},
            {
                1: 2, 'c': 3,
                'g': lambda x: x ** 2,
                't': dict(c=print, z=2),
            },
            {},
            frozenset({1, 2, }),
            max, min, NotImplemented,
            range(10), 7 + 8.0j,
        ],
        'vbytes_': b'klsdjflkds\\\x00',
        'empty_str': '',
        'ba': bytearray(b'a' * 20),
        'long_list': [123, {'1', b'klsdjf'}] * 10,
        'np_object': np.array([[1, 2, ], [3, 4]]),
        'np_module': np,
        'typing_': Callable[[int, str], Dict[str, List[int]]],
    }, reformat='pep8')  # auto reformat the code
    print(_code)

The output result (as well as the dumped script) should be

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import math
from builtins import frozenset, object
from typing import Any, Callable, Dict, List

import numpy
from numpy import ndarray
from potc.supports import function, typed_object

__all__ = [
    'ba', 'complex_array', 'empty_str', 'long_list', 'np_module', 'np_object',
    'typing_', 'vbytes_'
]
ba = bytearray(b'aaaaaaaaaaaaaaaaaaaa')
complex_array = [
    1, 1.5, math.e,
    typed_object(
        object,
        b'x\x9ck`NN\xc9\xcc\xc9\xd1\x8b\x07\x91\\\xf19\xf9\x89)\xf1%\x95\x05\xa9\\\x85\x0c\x11l\x0c\x0c\x0c\xf9IY\xa9\xc9%\x85\x8c\xad\x85LA\x85\xcc\x9a\x8d\x85,z\x00\xb3Q\x0f\xb5'
    ), math.nan, +math.inf, -math.inf, 'str', None,
    {1, 2, 'tttttttttttttttttttttttttttttt'}, {
        1:
        2,
        'c':
        3,
        'g':
        function(
            '<lambda>', Callable[[Any], Any],
            b'x\x9cm\x90Mk\x83@\x18\x84W\xd36\xd6~$\xa5\x7f"^\\4\xc6\xb8Pz\xf1(\xe4\x90^\xbc\xbd\xac\xbb\x86H\xd5\xcd\xeb\xaei\x03\x15zi~wM\xcf=<\xc3\xc0\xc0\x0c\xcc\xf7D\xc8\xaa\xae}\xb8\xa8\x0b\xa2+\xb9)a\xd7\xb7\xc2T\xaau\x91,\xfe\xcb\x85\x92\xa5\x8b\xd6"\xb322bgi\xea|\x11i=\x937\x82\xf6&\xb3\xcf8\xf1r\x8b\x10\xf2\x89W?x\x9d\xefGKMs\xb8\x10\xc4\'v\x8c\xd6\x1f\x94\x85A$\xf8:LX\x11\x0b\xc6v\x05gQ\x10-WI\xccVQ\x18\xc5\x82/E \xcb\x84J%4\xd5\xaa\xefDIMoTW\xf1ZS\xec+\xf1\x0e\xda\xf0\xce\xd0#\xef\xb4/\xcbF\xf9\x87\x13\xde\xe4\xce8\xf7R\xf3\xa6\x90\xfc\x15\xa7\xd9<%\xe8x\x9e\xc1\xdb-\xba\x02\xa0\xe8\xab\xdaT-\x80\x0b\xd0\xf0?\xb3\x9fn6\x06\xef\xb6x?\xe0\xc3\x80\x8f\xf9l\xac\x00\xe0m\xab\x0c\xbf\\\xa1\x01p6\xe0\\\x9f\xf1\xa9\xf0\x7f\x01\x08K^\xe0'
        ),
        't': {
            'c': print,
            'z': 2
        }
    }, {},
    frozenset({1, 2}), max, min, NotImplemented,
    range(10), (7 + 8j)
]
empty_str = ''
long_list = [
    123, {'1', b'klsdjf'}, 123, {'1', b'klsdjf'}, 123, {'1', b'klsdjf'}, 123,
    {'1', b'klsdjf'}, 123, {'1', b'klsdjf'}, 123, {'1', b'klsdjf'}, 123,
    {'1', b'klsdjf'}, 123, {'1', b'klsdjf'}, 123, {'1', b'klsdjf'}, 123,
    {'1', b'klsdjf'}
]
np_module = numpy
np_object = typed_object(
    ndarray,
    b"x\x9c-\x8b\xb9\x12\x820\x18\x84s\xe0\x15\xcfG\xb0\xa4JmaGgfRP\xd1e0\xa4`\x86\xeb\x8f\xa1\xa0\xb3Q\xe4\xa9\x15$[\xec7\xb3\xc7\x93\xea,/\n\xae&gJ[\x93:\xa3Rk\xd3\x8e\x01\nu\xd5\x96M\xc7um\r/\xdb\xc2\xe5s\xa3\xac\xd1u\xf5p\xb6\xd5\x8e\x01\x9eW\xac\xca\xfc\x8f\x08\xf4\x02\x1a\xe1;\x04=,B\x81\x05\x11\xe4\rK\xbf\xcb\\\xd7\x18\x06\xab\x84 \x84\xf2\x0b\xac\x87O\x0f\x9b\x18X(h\x82\xc7\xec\n[)\xe5\xed;\xeao\x029\xd8\xdd\x87\xe8<\x95\x93\x88'\xf5\x0c<a\xef\xe0 \x1d\x1cc8\xf1\x1f\x14\xb8?\xa9"
)
typing_ = Callable[[int, str], Dict[str, List[int]]]
vbytes_ = b'klsdjflkds\\\x00'

It is runnable, you can take a try.

Define My Rules

In the example above, numpy objects are translated as the serialized bytes, it is not as visible as we expected. Besides, you may think that the dictionary which is expressed with {} format is so ugly that you want to optimize the expression.

You can define your own rule like the example below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import re

import numpy as np

from potc import transvars
from potc.fixture import rule, Addons
from potc.rules import builtin_dict


@rule(type_=np.ndarray)
def ndarray_(v, addon: Addons):
    with addon.transaction():
        return addon.obj(np, 'np').array(v.tolist())


_VAR_NAME = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*$')


@rule(type_=dict)
def my_dict(v: dict, addon: Addons):
    if all([isinstance(key, str) and _VAR_NAME.fullmatch(key) for key in v.keys()]):
        return addon.val(type(v))(**v)
    else:
        addon.unprocessable()  # give up rule replacing


if __name__ == '__main__':
    _code = transvars({
        'np_objects': {
            'a': np.array([[1, 2, ], [3, 4]]),
            'b': {
                'c': np.array([1, 2, 3]),
                'd': np.zeros((2, 3)),
                't': 233,
            },
            'e': {
                '0': np.array([1, 2]),
                'p': 2j,
                'f': {
                    123: np.ones((3, 2)),
                    None: np.zeros((1, 5)),
                },
                'g': {
                    'a': 'dict here.'
                }
            },
        },
        'np_module': np,
    }, [
        ndarray_,  # rule for np.ndarray
        (my_dict, builtin_dict,),  # rule for dict, before `builtin_dict`
    ], reformat='pep8')  # auto reformat the code
    print(_code)

The output result (as well as the dumped script) should be

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import numpy
import numpy as np

__all__ = ['np_module', 'np_objects']
np_module = numpy
np_objects = dict(a=np.array([[1, 2], [3, 4]]),
                  b=dict(c=np.array([1, 2, 3]),
                         d=np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]),
                         t=233),
                  e={
                      '0': np.array([1, 2]),
                      'p': 2j,
                      'f': {
                          123: np.array([[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]]),
                          None: np.array([[0.0, 0.0, 0.0, 0.0, 0.0]])
                      },
                      'g': dict(a='dict here.')
                  })

Now you can see the dictionaries will be expressed with dict form when the keys is allowed to do so, the np.ndarray objects will be expressed with the visible format as well.

Use CLI For Translating

In potc, cli is provided to quickly generate python code. For example, you can translate an object with potc trans command. Firstly, here is the content of python source file data.py

1
2
3
4
5
6
7
8
import math

v_a = [1, 'kdfgjs', None, math.pi]
v_b = {
    'a': v_a,
    'b': (3, 4, 'dfg'),
    0: {'a': 3, 'b': None, 'c': math.e}
}

based on this, we can translate v_a from data.py by this command

1
potc trans data.v_a

The output should be

1
[1, 'kdfgjs', None, math.pi]

Also, if you need to take a look at the full information of this translation, you can use -I option to display them, like this

1
potc trans data.v_b -I

The output (including information) should be

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Object Information:
Module : data
Name : v_b
Type : dict

Import Statements:
import math

Expression:
{'a': [1, 'kdfgjs', None, math.pi], 'b': (3, 4, 'dfg'), 0: {'a': 3, 'b': None, 'c': math.e}}

In further cases, we may need to directly dump a runnable python source code and then maybe execute it. You can dump the variables from data.py by this command

1
potc export -v 'data.v_*'

The dumped code should be

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import math

__all__ = ['v_a', 'v_b']
v_a = [1, 'kdfgjs', None, math.pi]
v_b = {
    'a': [1, 'kdfgjs', None, math.pi],
    'b': (3, 4, 'dfg'),
    0: {
        'a': 3,
        'b': None,
        'c': math.e
    }
}

Besides, you can use your self-defined rules to change the dumping result, like this

1
potc export -v 'data.v_*' -r plugins.potc_dict.potc_dict.plugin.__rules__

The new dumped code should be

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import math
from builtins import dict

__all__ = ['v_a', 'v_b']
v_a = [1, 'kdfgjs', None, math.pi]
v_b = {
    'a': [1, 'kdfgjs', None, math.pi],
    'b': (3, 4, 'dfg'),
    0: dict(a=3, b=None, c=math.e)
}