A python wrapper for the Humon C API.
Project description
humon
A Python wrapper for the Humon C API. This project uses Cython, so can theoretically be used wherever Cython modules can be used.
Installation
Thus far, the Python wrapper has only been tested on Linux-like systems. Available as a PyPI package:
$ pip install humon
Or, you can clone it from github:
$ git clone https://github.com/spacemeat/humon-cy
$ pip install ./humon-cy
It's best practice to emplace it in a virtual environment.
API overview
See the Humon project readme for comprehensive details about Humon's format. This readme only describes the Python interface. The API is not strictly 1-1 with the C/C++ APIs.
Loading troves
Easy. There are two ways:
import humon as h
eqipment_trove = h.from_file('equipment.hu') # default encoding = h.Encoding.UNKNOWN
quests_trove = h.from_file('equipment.hu', h.Encoding.UTF8)
import humon as h
trove = h.from_string('{foo: bar}')
The file on disk may be encoded with any UTF-n format, as in the C API. Python strings are already Unicode-encoded, and will be converted to UTF-8 (Humon's internal format) if need be.
The returned trove
is the container for the Humon data. It will hold the entire file or string, and provide very quick access to the contents for reading once loaded. Troves are immutable once created.
Both functions also take an optional parameter
tab_size: int
. This is to help error diagnostics determine the correct column.
Accessing nodes
For much of the rest of this document, we'll utilize a sample Humon file on disk:
$ cat gnome.hu
@ { app: gamin'-djinn, component: assets-gnome, version: 0.1.0 }
{
model: gnome-generic.fbx
textures: [
gnome-generic-albedo.png
gnome-generic-bump.png @ units: model-space
gnome-generic-metallic.png
]
animations: {
idle: [
gnome-idle_0.anim
gnome-idle_1.anim
]
}
}
Humon data is a tree of nodes: lists, dicts, and values, organized like JSON data. There are also comments and annotations, and all of this is described in the Humon project readme. Currently, comments cannot be accessed through the API, though that is forthcoming.
Getting the root node is done through the root
property of a trove:
import humon as h
trove = h.from_string('{foo: [a b c d]}')
root = trove.root
The returned object is of type Node
. You can access its kind--list, dict, value--by the kind
property. A list or dict will have child nodes, accessible through getitem(). Any child of a dict will have a key
property. A value node will have a value
property.
import humon as h
trove = h.from_string('{foo: [a b c d]}')
root = trove.root
assert root.kind == NodeKind.DICT
lnode = root['foo']
vnode = lnode[2]
print (vnode.value) # prints: c
A minor difference between Humon and JSON is that Humon dict entries can be accessed by index as well, and keep their order as loaded. (This is a strict language feature, and not dependent on any API.)
import humon as h
trove = h.from_string('{foo: foofoo, bar: barbar, baz: bazbaz}')
vnode = trove.root[2]
print (vnode.value) # prints bazbaz
Another minor difference between Humon and JSON is that Humon dicts do not have to have unique keys. You can access the nth child node with a given key:
import humon as h
trove = h.from_string('''{ foo: [a b c d]
bar: snaa
foo: [e f g h]
baz: plugh
foo: [i j k l] }''')
vnode = trove.root['foo', 2]
print (f'{vnode.address}: {vnode.value}') # prints: /foo: [i j k l]
You can also access nodes via address:
import humon as h
trove = h.from_string('{foo: [a b c d]}')
vnode = trove.get_node('/foo/2')
print (f'{vnode.address}: {vnode.value}') # prints: /foo/2: c
vnode = vnode.get_node('../3')
print (f'{vnode.address}: {vnode.value}') # prints: /foo/3: d
Nodes which share a parent are sibling
nodes:
import humon as h
trove = h.from_string('{foo: [a b c d] bar: [e f g h]}')
vnode = trove.get_node('/foo')
print (f'{vnode.address}: {vnode.value}') # prints: /foo: [a b c d]
vnode = vnode.get_sibling('bar')
print (f'{vnode.address}: {vnode.value}') # prints: /bar: [e f g h]
vnode = vnode[0].sibling()
print (f'{vnode.address}: {vnode.value}') # prints: /bar/0: e
A trove stores nodes as a linear array internally, and nodes can be accessed by index from the Trove ojbect:
import humon as h
trove = h.from_string('{foo: [a b c d]}')
print (trove.get_node(4).value) # prints: c
Annotations
Annotations on a trove or node are returned as dicts. Assuming a reasonable implementation of a Version class:
import humon as h
data = '''@ { app: gamin'-djinn, component: assets-gnome, version: 0.1.0 }
{
model: gnome-generic.fbx
textures: [
gnome-generic-albedo.png
gnome-generic-bump.png @ units: model-space
gnome-generic-metallic.png
]
animations: {
idle: [
gnome-idle_0.anim
gnome-idle_1.anim
]
}
}'''
trove = h.from_string(data)
to = trove.annotations
assert to['app'] == "gamin'-djinn"
if Version(to['version']).in_range('0.0.4', '0.1.3'):
print (trove.get_node('/textures/1').annotations) # prints: {'units': 'model-space'}
Serializing
Though a trove is immutable, it can be printed in a few ways. The most useful maybe is with Trove.to_string() and Trove.to_file():
...
s = trove.to_string(h.WhitespaceFormat.MINIMAL, print_comments = False)
The minimal formatting reduces the whitespace to a minimum while keeping Humon semantics the same. You can do a pretty formatting as well:
...
trove.to_file(path: 'pretty.h',
whitespace_format = h.WhitespaceFormat.PRETTY, indent_size = 4,
indent_with_tabs = False, use_colors = True, color_table = None,
print_comments = True, newline = '\n', print_bom = True)
Passing True
to use_colors
will insert colorizing markup entries appropriately in the resutlant string. If you specify use_colors
, but do not provide a color table, the API will use some ANSI color codes as default values. Set color entries for each color type like so:
...
named_fg = {
'black': '\033[30m',
'red': '\033[31m',
'green': '\033[32m',
'yellow': '\033[33m',
'blue': '\033[34m',
'magenta': '\033[35m',
'cyan': '\033[36m',
'white': '\033[37m',
'bright black': '\033[90m',
'bright red': '\033[91m',
'bright green': '\033[92m',
'bright yellow': '\033[93m',
'bright blue': '\033[94m',
'bright magenta': '\033[95m',
'bright cyan': '\033[96m',
'bright white': '\033[97m',
}
color_table = {
h.ColorCode.TOKENSTREAMBEGIN: '',
h.ColorCode.TOKENSTREAMEND: '\033[0m',
h.ColorCode.TOKENEND: '',
h.ColorCode.PUNCLIST: named_fg['bright white'],
h.ColorCode.PUNCDICT: named_fg['bright white'],
h.ColorCode.PUNCKEYVALUESEP: named_fg['bright white'],
h.ColorCode.PUNCANNOTATE: named_fg['bright blue'],
h.ColorCode.PUNCANNOTATEDICT: named_fg['bright blue'],
h.ColorCode.PUNCANNOTATEKEYVALUESEP: named_fg['blue'],
h.ColorCode.KEY: named_fg['cyan'],
h.ColorCode.VALUE: named_fg['bright cyan'],
h.ColorCode.COMMENT: named_fg['red'],
h.ColorCode.ANNOKEY: named_fg['magenta'],
h.ColorCode.ANNOVALUE: named_fg['bright magenta'],
h.ColorCode.WHITESPACE: named_fg['white'],
}
trove.to_file(path: 'pretty.h',
whitespace_format = h.WhitespaceFormat.PRETTY, indent_size = 4,
indent_with_tabs = False, use_colors = True, color_table = color_table,
print_comments = True, newline = '\n', print_bom = True)
You can also access full text in a node or trove with token_string
:
import humon as h
trove = h.from_string('{foo: [a b {color: {green: [froggy, leafy]}} d]}')
print (trove.get_node('/foo/2').token_string) # prints: {green: [froggy, leafy]}}
print (trove.token_string) # prints the whole trove
Calling
token_string
on the trove is nearly equivalent to calling 'Trove.to_string' withwhitespace_format
set tohumon.WhitespaceFormat.CLONED
and no colors. But, since it copies directly from the loaded text, it is much faster.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file humon-0.1.0.tar.gz
.
File metadata
- Download URL: humon-0.1.0.tar.gz
- Upload date:
- Size: 181.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.0 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 48db90b0031f395ad84280df45ba403bb6f21e969c5b4d7b7c1fa0efdbfe37eb |
|
MD5 | 417e347e0f104374cf6492df524ce7a9 |
|
BLAKE2b-256 | 86bf155ca0a354b2c216fdf60ade895437d8428a88d9268cacd9754ba1b997d9 |