Skip to main content

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' with whitespace_format set to humon.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

humon-0.1.0.tar.gz (181.5 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page