https://github.com/perfecto25/rio_config
Rio config parser
https://github.com/perfecto25/rio_config
configuration markup parser rio syntax
Last synced: 7 months ago
JSON representation
Rio config parser
- Host: GitHub
- URL: https://github.com/perfecto25/rio_config
- Owner: perfecto25
- Created: 2025-02-25T21:55:22.000Z (11 months ago)
- Default Branch: master
- Last Pushed: 2025-06-10T12:36:32.000Z (8 months ago)
- Last Synced: 2025-06-20T18:12:25.228Z (8 months ago)
- Topics: configuration, markup, parser, rio, syntax
- Language: Python
- Homepage:
- Size: 312 KB
- Stars: 6
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Rio Config data parser

Rio is a configuration parser for use in common configuration scenarios.
It is similar to TOML and YAML in concept, but is unique in its approach to handling variables and configuration data, with focus on simplicity of declaration of complex data structures.
## Features
- no spacing requirements (ie, 2 spaces in YAML)
- braces not necessary (ie, json)
- can add comments inside configuration
- clean and simple syntax to describe complex data structures
- ability to create template blocks for repeated options
- can natively ingest shell environment variables at runtime, including fallback values
- ability to created nested hashes without excessive notation and spacing
## Installation
To install Rio Config, using pip
pip install rio_config
---
## Usage
To parse a rio configuration file and get a dictionary structure of your file:
from rio_config import Rio
rio = Rio()
result = rio.parse_file("myfile.rio")
Rio can handle the following types
- strings
- hashes
- ints
- floats
- booleans
- arrays
To create a basic key:value pair, you need a Header block (top key or Parent key) which is denoted by colon at end
Key:
Value
ie,
Name:
"Joe"
# equals {"Name": "Joe"}
To created a nested hash
Parent Key:
child key = child value
Employee:
Name = "Joe"
# equals {"Employee": {"Name": "Joe"}}
double quoting non numeric values is recommended to avoid ambiguous value declaration
---
### Basic Dictionary/Hash
To create a deep hash structure, add a key block declaration of all top keys and a final value, separated by a dot
Rio will create all parent subkeys along the path
first.second.third:
fourth = value
result
{
"first": {
"second": {
"third": {
"fourth": "value"
}
}
}
}
double spacing the subkey=value is not mandatory but is recommended for readability, ie
first.second.third:
fourth = value
---
### Escape Character
if the top level key has dot in its name, you can escape parsing it with an escape character '\\.'
first.second\.level.third:
value
result
{
"first": {
"second.level": {
"third": "value"
}
}
}
---
### Single Key
If the Parent key has dots in the name and you want to keep it as single key, double quote the parent key
"parent.key.separated.by.dot":
subkey = value
result
{
"parent.key.separated.by.dot": {
"subkey": "value"
}
}
---
### Arrays
To create an array, declare it using brackets, with each element separated by a comma
My List:
subkey = [first, second, third]
## result
{
"My List": {
"subkey": [
"first",
"second",
"third"
]
}
}
Arrays can also be created using a multiline declaration within a bracket pair
cars:
names = [
toyota,
ferrari,
chevy
]
result
{
"cars": {
"names": [
"toyota",
"ferrari",
"chevy"
]
}
}
you can also create an array without a subkey,
my array:
['a', 'b', 'c']
result
{
"my array": [
"a",
"b",
"c"
]
}
---
### Child nested subkeys
With Rio you can also create nested subkeys underneath your parent key, by placing a dot in the subkey declaration
config.nginx:
cache.size = 200
cache.limit = 190
cache.clean.size = 5
result
{
"config": {
"nginx": {
"cache": {
"size": 200,
"limit": 190,
"clean": {
"size": 5
}
}
}
}
}
To treat a child subkey with dots as a single key, wrap it in quotes
config.nginx:
cache.size = 200
cache.limit = 190
"cache.clean.size" = 5
---
### Strings, Ints, Booleans, Floats
Rio will evaluate each value for its type, ie strings, ints, floats, booleans
By default, all values are strings, unless its a raw integer. To treat an integer as a string, double quote it
variables:
string = this is a string
real int = 12345
stringified int = "12345"
boolean true = True
boolean false = False
boolean strinfigied = "True"
float = 2.34596
result
{
"variables": {
"string": "this is a string",
"real int": 12345,
"stringified int": "12345",
"boolean true": true,
"boolean false": false,
"boolean strinfigied": "True",
"float": 2.34596
}
}
---
### Templates
Templates allow you to reuse configuration data without copying and pasting the same data over and over.
Templates are created by using the @template keyword
**@template TemplateName:** declares a new template, followed by template variables
**@use** keyword then instructs the key block to use the variables from the given template, ie
@use = myTemplate
for example, lets say you want to add some Company-specific data to every Employee
(note: double spacing the subkeys is not mandatory but recommended, purely for visual clarity)
@template company:
name = "Initech"
address = "123 company drive"
phone = "200-301-4050"
employees.Joe:
@use = company
department = "sales"
employees.Bill:
@use = company
department = "engineering"
result:
{
"employees": {
"Joe": {
"name": "Initech",
"address": "123 company drive",
"phone": "200-301-4050",
"department": "sales"
},
"Bill": {
"name": "Initech",
"address": "123 company drive",
"phone": "200-301-4050",
"department": "engineering"
}
}
}
to overwrite a template's variable with a custom value, simply provide a new variable with same name
for example, if you want Bill's phone number to be 111-111-1111 instead of the phone number from the template, you can add a new variable called "phone" which will override the previous value coming from the template
@template company:
name = Initech
address = "123 company drive"
phone = "200-301-4050"
employees.Joe:
@use = company
department = "sales"
employees.Bill:
@use = company
department = "engineering"
phone = "111-111-1111"
result
{
"employees": {
"Joe": {
"name": "Initech",
"address": "123 company drive",
"phone": "200-301-4050",
"department": "sales"
},
"Bill": {
"name": "Initech",
"address": "123 company drive",
"phone": "111-111-1111",
"department": "engineering"
}
}
}
You can also combine multiple templates in one config block
@template evens:
even_numbers = [2,4,6,8]
@template odds:
odd_numbers = [1,3,5,7]
@template words:
hello = world
bunch of words = [
sunflower,
gunpowder,
beer
]
combined stuff:
@use = evens
@use = odds
@use = words
result will contain all your template variables
{
"combined stuff": {
"even_numbers": [
2,
4,
6,
8
],
"odd_numbers": [
1,
3,
5,
7
],
"hello": "world",
"bunch of words": [
"sunflower",
"gunpowder",
"beer"
]
}
}
---
### Multiline Comments
comments or text spanning multiple lines can be written using the single quote troika
mycomment:
comment = '''
this
is
a comment
that spans
many
lines
'''
result
{
"mycomment": {
"comment": "\nthis \nis \na comment\nthat spans\n\nmany\n\nlines\n"
}
}
---
### Environment Variables
to process a shell environment variable, provide @env flag
database.credential:
password = @env DB_PASSWORD
this will translate a shell variable $DB_PASSWORD
if the variable is not set, the value will be NULL
to pass a default fallback value if env variable isnt set, provide a default using the double pipe OR symbol
database.credential:
password = @env DB_PASSWORD || abracadabra123
result
{
"database": {
"credential": {
"password": "abracadabra123"
}
}
}
```bash
export DB_PASSWORD="cheese-is-yummy991"
```
{
"database": {
"credential": {
"password": "cheese-is-yummy991"
}
}
}
---
### Comments
Comments within the configuration data can be added with # symbol
# this is a comment
key:
value # this is also a comment
Comments are not processed during final output
---
### Testing
pip install pytest
shell> cd tests
shell> pytest -sv run_tests.py
---
### Packaging
python3 -m pip install --upgrade pip setuptools wheel build twine
python3 -m build
python3 -m pip install twine
python3 -m twine upload dist/*
## TO DO:
- add single variables ie $var = joe
use var,
name = $var
- add For loops