First Commit
On branch master Initial commit Changes to be committed: new file: .gitignore new file: .python-version new file: README.md new file: main.py new file: pyproject.toml new file: src/constructor/__init__.py new file: src/constructor/construct.py
This commit is contained in:
177
.gitignore
vendored
Normal file
177
.gitignore
vendored
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
# ---> Python
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# UV
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
#uv.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||||
|
.pdm.toml
|
||||||
|
.pdm-python
|
||||||
|
.pdm-build/
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
# Ruff stuff:
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# PyPI configuration file
|
||||||
|
.pypirc
|
||||||
|
|
||||||
|
|
||||||
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.12
|
||||||
6
main.py
Normal file
6
main.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
def main():
|
||||||
|
print("Hello from constructor!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
13
pyproject.toml
Normal file
13
pyproject.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[project]
|
||||||
|
name = "constructor"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Custom Wrapper Around builtin Struct class"
|
||||||
|
authors = [{name = "TSD", email = "t.s.davis6291@gmail.com"}]
|
||||||
|
readme = "README.md"
|
||||||
|
license = "APACHE2.0"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
dependencies = []
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["uv-build"]
|
||||||
|
build-backend = "uv_build"
|
||||||
11
src/constructor/__init__.py
Normal file
11
src/constructor/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from construct import (
|
||||||
|
struct_formatter,
|
||||||
|
structBSA,
|
||||||
|
bType
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'struct_formatter',
|
||||||
|
'structBSA',
|
||||||
|
'bType'
|
||||||
|
]
|
||||||
377
src/constructor/construct.py
Normal file
377
src/constructor/construct.py
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
import struct
|
||||||
|
from dataclasses import dataclass,asdict
|
||||||
|
import sys
|
||||||
|
import platform
|
||||||
|
|
||||||
|
class structBSA:
|
||||||
|
|
||||||
|
_validators = '@=<>!'
|
||||||
|
_values = {
|
||||||
|
'@' : ( 'native' , 'native' , 'native' ),
|
||||||
|
'=' : ( 'native' , 'standard' , None ),
|
||||||
|
'<' : ( 'little-endian' , 'standard' , None ),
|
||||||
|
'>' : ( 'big-endian' , 'standard' , None ),
|
||||||
|
'!' : ( 'network' , 'standard' , None )
|
||||||
|
}
|
||||||
|
|
||||||
|
_native = sys.byteorder
|
||||||
|
_arch = platform.machine()
|
||||||
|
|
||||||
|
if '64' in _arch:
|
||||||
|
_size = 64
|
||||||
|
|
||||||
|
elif '32' in _arch or '86' in _arch:
|
||||||
|
_size = 32
|
||||||
|
|
||||||
|
else:
|
||||||
|
_size = None
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
char:str
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
if char in self._validators:
|
||||||
|
|
||||||
|
self.char = char
|
||||||
|
|
||||||
|
self.byte_order,\
|
||||||
|
self.size,\
|
||||||
|
self.alignment = self._values[char]
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
result = ''
|
||||||
|
values = {
|
||||||
|
'Native' : self._native,
|
||||||
|
'Architecture' : self._arch,
|
||||||
|
'AddressSpace' : self._size,
|
||||||
|
'Character' : self.char,
|
||||||
|
'ByteOrder' : self.byte_order,
|
||||||
|
'Size' : self.size,
|
||||||
|
'Alignment' : self.alignment
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ct_1,\
|
||||||
|
ct_2,\
|
||||||
|
cb_1,\
|
||||||
|
cb_2 = ('\u250E','\u2512','\u2516','\u251A')
|
||||||
|
|
||||||
|
jl,\
|
||||||
|
jr,\
|
||||||
|
jd,\
|
||||||
|
ju,\
|
||||||
|
jq = ('\u2520','\u2528','\u252F','\u2537','\u253f')
|
||||||
|
|
||||||
|
edges = ('\u2502','\u2501')
|
||||||
|
ev,eh = edges
|
||||||
|
|
||||||
|
lines:list[
|
||||||
|
list[str]
|
||||||
|
] = [[],[],[],[],[]]
|
||||||
|
|
||||||
|
n = 0
|
||||||
|
n_stop = len(values) - 1
|
||||||
|
|
||||||
|
for header,value in values.items():
|
||||||
|
|
||||||
|
line_1 = ''
|
||||||
|
line_2 = ''
|
||||||
|
line_3 = ''
|
||||||
|
line_4 = ''
|
||||||
|
line_5 = ''
|
||||||
|
value = str(value)
|
||||||
|
|
||||||
|
field_length = max(len(header),len(value)) + 2
|
||||||
|
|
||||||
|
if len(header) %2 != 0:
|
||||||
|
header += ' '
|
||||||
|
|
||||||
|
if len(value) %2 != 0:
|
||||||
|
value += ' '
|
||||||
|
|
||||||
|
while len(header) < field_length:
|
||||||
|
|
||||||
|
header = f' {header} '
|
||||||
|
|
||||||
|
if len(header) >= field_length:
|
||||||
|
break
|
||||||
|
|
||||||
|
while len(value) < field_length:
|
||||||
|
|
||||||
|
value = f' {value} '
|
||||||
|
|
||||||
|
if len(value) >= field_length:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
line_2 += f'{ev}{header}'
|
||||||
|
line_4 += f'{ev}{value}'
|
||||||
|
|
||||||
|
match n:
|
||||||
|
case 0:
|
||||||
|
|
||||||
|
line_1 = f'{ct_1}{eh * field_length}'
|
||||||
|
|
||||||
|
line_3 = f'{jl}{eh * field_length}'
|
||||||
|
|
||||||
|
line_5 = f'{cb_1}{eh*field_length}'
|
||||||
|
|
||||||
|
case _:
|
||||||
|
|
||||||
|
line_1 = f'{jd}{eh*field_length}'
|
||||||
|
|
||||||
|
line_3 = f'{jq}{eh*field_length}'
|
||||||
|
|
||||||
|
line_5 = f'{ju}{eh*field_length}'
|
||||||
|
|
||||||
|
if len(line_2) != len(line_3):
|
||||||
|
|
||||||
|
while len(line_2) != len(line_3):
|
||||||
|
|
||||||
|
line_1 += eh
|
||||||
|
line_3 += eh
|
||||||
|
line_5 += eh
|
||||||
|
|
||||||
|
if len(line_2) == len(line_3):
|
||||||
|
break
|
||||||
|
|
||||||
|
if n == n_stop:
|
||||||
|
|
||||||
|
line_1 += ct_2
|
||||||
|
line_2 += ev
|
||||||
|
line_3 += jr
|
||||||
|
line_4 += ev
|
||||||
|
line_5 += cb_2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lines[0].append(line_1)
|
||||||
|
lines[1].append(line_2)
|
||||||
|
lines[2].append(line_3)
|
||||||
|
lines[3].append(line_4)
|
||||||
|
lines[4].append(line_5)
|
||||||
|
n += 1
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
full_line = ''.join(line)
|
||||||
|
result += f'{full_line}\n'
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
|
||||||
|
return self.char
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class bType(str):
|
||||||
|
|
||||||
|
def __new__(cls,designator):
|
||||||
|
return super().__new__(cls, designator)
|
||||||
|
|
||||||
|
_values = {
|
||||||
|
'x' : ( '\x00' , None , 0 ),
|
||||||
|
'c' : ( 'char' , bytes , 1 ),
|
||||||
|
'b' : ( 'signed char' , int , 1 ),
|
||||||
|
'B' : ( 'unsigned char' , int , 1 ),
|
||||||
|
'?' : ( '_Bool' , bool , 1 ),
|
||||||
|
'h' : ( 'short' , int , 2 ),
|
||||||
|
'H' : ( 'unsigned short' , int , 2 ),
|
||||||
|
'i' : ( 'integer' , int , 4 ),
|
||||||
|
'I' : ( 'unsigned integer' , int , 4 ),
|
||||||
|
'l' : ( 'long' , int , 4 ),
|
||||||
|
'L' : ( 'unsigned long' , int , 4 ),
|
||||||
|
'q' : ( 'long long' , int , 8 ),
|
||||||
|
'Q' : ( 'unsigned long long' , int , 8 ),
|
||||||
|
'n' : ( 'ssize_t' , int , None ),
|
||||||
|
'N' : ( 'size_t' , int , None ),
|
||||||
|
'e' : ( 'f16' , float , 2 ),
|
||||||
|
'f' : ( 'f32' , float , 4 ),
|
||||||
|
'd' : ( 'f64' , float , 8 ),
|
||||||
|
's' : ( 'char[]' , bytes , None ),
|
||||||
|
'p' : ( 'char[]' , bytes , None ),
|
||||||
|
'P' : ( 'void*' , int , None )
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self,designator:str):
|
||||||
|
self.designator = designator
|
||||||
|
self.c_type,self.type_of,self.size = self._values[designator]
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
|
||||||
|
headers = (
|
||||||
|
'Symbol',
|
||||||
|
'CType' ,
|
||||||
|
'PyType',
|
||||||
|
'Size'
|
||||||
|
)
|
||||||
|
|
||||||
|
title = 'DataStructure'
|
||||||
|
|
||||||
|
type_1 = f'{self.c_type}'
|
||||||
|
type_2 = f'{str(self.type_of).replace('class ','')}'
|
||||||
|
|
||||||
|
size = f'{self.size}' if self.size is not None else '0x00'
|
||||||
|
|
||||||
|
align_val = max([len(s) for s in [type_1,type_2,size,*headers]]) + 2
|
||||||
|
|
||||||
|
top_line = ' ' + ('\u2500' * (((align_val + 1) * 4) - 1))
|
||||||
|
line_1 = ' \u2502'
|
||||||
|
|
||||||
|
for header in headers:
|
||||||
|
|
||||||
|
unused_space = (align_val - len(header)) // 2
|
||||||
|
|
||||||
|
if len(header) + (unused_space * 2) != align_val:
|
||||||
|
header = ' ' + header
|
||||||
|
line_1 += f'{' ' * unused_space}{header}{' ' * unused_space}\u2502'
|
||||||
|
|
||||||
|
line_2 = ' \u251c'
|
||||||
|
|
||||||
|
for _ in range(4):
|
||||||
|
line_2 += ('\u2500' * (align_val)) + '\u253C'
|
||||||
|
|
||||||
|
line_2 = f'{line_2[:-1]}\u2524'
|
||||||
|
line_3 = ' \u2502'
|
||||||
|
|
||||||
|
if self.designator == 'x':
|
||||||
|
type_1 = 'NULL'
|
||||||
|
|
||||||
|
for data in (
|
||||||
|
self.designator,
|
||||||
|
type_1,
|
||||||
|
type_2,
|
||||||
|
size
|
||||||
|
):
|
||||||
|
|
||||||
|
unused_space = (align_val - len(data)) // 2
|
||||||
|
|
||||||
|
if len(data) + (unused_space*2) != align_val:
|
||||||
|
data = ' ' + data
|
||||||
|
|
||||||
|
line_3 += f'{' ' * unused_space}{data}{' ' * unused_space}\u2502'
|
||||||
|
|
||||||
|
line_4 = top_line
|
||||||
|
title_spacer = (len(top_line) // 2) - (len(title) // 2)
|
||||||
|
title = f'{' '*title_spacer}{title}'
|
||||||
|
|
||||||
|
top_line = f' \u250C{top_line[2:]}\u2510'
|
||||||
|
line_4 = f' \u2514{line_4[2:]}\u2518'
|
||||||
|
|
||||||
|
return '\n'.join([title,top_line,line_1,line_2,line_3,line_4])
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.designator
|
||||||
|
|
||||||
|
@property
|
||||||
|
def c(self):
|
||||||
|
return self.designator
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class struct_formatter:
|
||||||
|
|
||||||
|
native :structBSA = structBSA('@')
|
||||||
|
native_std :structBSA = structBSA('=')
|
||||||
|
little_end :structBSA = structBSA('<')
|
||||||
|
big_end :structBSA = structBSA('>')
|
||||||
|
network :structBSA = structBSA('!')
|
||||||
|
|
||||||
|
pad :bType = bType('x')
|
||||||
|
char :bType = bType('c')
|
||||||
|
schar :bType = bType('b')
|
||||||
|
uchar :bType = bType('B')
|
||||||
|
_Bool :bType = bType('?')
|
||||||
|
short :bType = bType('h')
|
||||||
|
ushort :bType = bType('H')
|
||||||
|
integer :bType = bType('i')
|
||||||
|
uint :bType = bType('I')
|
||||||
|
long :bType = bType('l')
|
||||||
|
ulong :bType = bType('L')
|
||||||
|
longlong :bType = bType('q')
|
||||||
|
ulonglong :bType = bType('Q')
|
||||||
|
ssize_t :bType = bType('n')
|
||||||
|
size_t :bType = bType('N')
|
||||||
|
f16 :bType = bType('e')
|
||||||
|
f32 :bType = bType('f')
|
||||||
|
f64 :bType = bType('d')
|
||||||
|
string :bType = bType('s')
|
||||||
|
pascal :bType = bType('p')
|
||||||
|
void :bType = bType('P')
|
||||||
|
|
||||||
|
def _todict(self) -> dict[str,structBSA|bType]:
|
||||||
|
return asdict(self)
|
||||||
|
|
||||||
|
def compile(self,*args):
|
||||||
|
str_head = ''
|
||||||
|
str_tail = ''
|
||||||
|
for arg in args:
|
||||||
|
match arg:
|
||||||
|
case structBSA():
|
||||||
|
str_head += arg.char
|
||||||
|
case tuple():
|
||||||
|
str_plus = ''.join([str(a) for a in arg])
|
||||||
|
str_tail += str_plus
|
||||||
|
case bType():
|
||||||
|
str_tail += arg
|
||||||
|
case str():
|
||||||
|
if arg in structBSA._validators:
|
||||||
|
str_head += arg
|
||||||
|
else:
|
||||||
|
str_tail += arg
|
||||||
|
case int():
|
||||||
|
str_tail += str(arg)
|
||||||
|
case _:
|
||||||
|
raise NotImplementedError
|
||||||
|
return struct.Struct(f'{str_head}{str_tail}')
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
result = ''
|
||||||
|
struct_formats:list[tuple[str,structBSA]] = []
|
||||||
|
struct_types:list[tuple[str,bType]] = []
|
||||||
|
formatter = struct_formatter()._todict()
|
||||||
|
for name,inst in formatter.items():
|
||||||
|
match inst:
|
||||||
|
case structBSA():
|
||||||
|
struct_formats.append((name,inst))
|
||||||
|
case bType():
|
||||||
|
struct_types.append((name,inst))
|
||||||
|
splicer = '\u252D\u2502\u253d\u2502\u2535'
|
||||||
|
for fmt in struct_formats:
|
||||||
|
for s_type in struct_types:
|
||||||
|
f_name,s_fmt = fmt
|
||||||
|
s_name,s_typ = s_type
|
||||||
|
fmt_lines = repr(s_fmt).splitlines()
|
||||||
|
typ_lines = repr(s_typ).splitlines()
|
||||||
|
lengths = []
|
||||||
|
for idx,line in enumerate(fmt_lines):
|
||||||
|
lengths.append(len(f'{typ_lines[idx]}{line}'))
|
||||||
|
new_repr = []
|
||||||
|
|
||||||
|
max_length = 4 + max(lengths)
|
||||||
|
title = typ_lines[0]
|
||||||
|
for idx,f_line in enumerate(fmt_lines):
|
||||||
|
t_line = splicer[idx] + typ_lines[idx+1][2:]
|
||||||
|
f_line = f_line[:-1]
|
||||||
|
spacer = max_length - len(f'\u2503 {f_line}{t_line}')
|
||||||
|
new_repr.append(f'\u2503 {f_line}{t_line}{' '*spacer}\u2503')
|
||||||
|
result += (f'\u250F{'\u2501' * (max_length - 1)}\u2513\n')
|
||||||
|
result += (
|
||||||
|
f'\u2503 {title.lstrip()}: {f_name}+{s_name} -> [\'{s_fmt.char}{s_typ.designator}\']{' '*(max_length - len(f'\u2503 {title.lstrip()}: {f_name}+{s_name} -> [\'{s_fmt.char}{s_typ.designator}\']'))}\u2503\n'
|
||||||
|
)
|
||||||
|
result += (f'\u2503{' '*((max_length - 1))}\u2503\n{'\n'.join(new_repr)}\n')
|
||||||
|
result += (f'\u2503{' '*(max_length - 1)}\u2503\n\u2517{'\u2501' * (max_length - 1)}\u251b\n')
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
s_dict = struct_formatter()._todict()
|
||||||
|
for key,value in s_dict.items():
|
||||||
|
spacer = (max([len(v) for v in repr(value).splitlines()]) // 2) - (len(key) // 2)
|
||||||
|
print(f'{' ' * spacer}{key}\n{value}')
|
||||||
|
print('\n\n')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user