{"id":28412420,"url":"https://github.com/perfecto25/rio_config","last_synced_at":"2025-06-24T12:31:20.110Z","repository":{"id":279512093,"uuid":"939027915","full_name":"perfecto25/rio_config","owner":"perfecto25","description":"Rio config parser","archived":false,"fork":false,"pushed_at":"2025-06-10T12:36:32.000Z","size":319,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-20T18:12:25.228Z","etag":null,"topics":["configuration","markup","parser","rio","syntax"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/perfecto25.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-02-25T21:55:22.000Z","updated_at":"2025-06-10T12:36:38.000Z","dependencies_parsed_at":"2025-06-03T04:30:34.799Z","dependency_job_id":null,"html_url":"https://github.com/perfecto25/rio_config","commit_stats":null,"previous_names":["perfecto25/gml","perfecto25/flex_markup","perfecto25/rio_config"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/perfecto25/rio_config","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perfecto25%2Frio_config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perfecto25%2Frio_config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perfecto25%2Frio_config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perfecto25%2Frio_config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/perfecto25","download_url":"https://codeload.github.com/perfecto25/rio_config/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perfecto25%2Frio_config/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260994062,"owners_count":23094287,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration","markup","parser","rio","syntax"],"created_at":"2025-06-02T21:41:42.607Z","updated_at":"2025-06-24T12:31:20.099Z","avatar_url":"https://github.com/perfecto25.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rio Config data parser\n\n\n\u003cimg src=\"./img/logo.png\"\u003e\n\nRio is a configuration parser for use in common configuration scenarios.\n\nIt 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.\n\n## Features\n- no spacing requirements (ie, 2 spaces in YAML)\n- braces not necessary (ie, json)\n- can add comments inside configuration\n- clean and simple syntax to describe complex data structures\n- ability to create template blocks for repeated options\n- can natively ingest shell environment variables at runtime, including fallback values\n- ability to created nested hashes without excessive notation and spacing\n\n## Installation\n\nTo install Rio Config, using pip\n\n    pip install rio_config\n\n\n---\n\n## Usage\n\nTo parse a rio configuration file and get a dictionary structure of your file:\n\n    from rio_config import Rio\n    \n    rio = Rio()\n    result = rio.parse_file(\"myfile.rio\")\n\n\nRio can handle the following types\n\n- strings\n- hashes\n- ints\n- floats\n- booleans\n- arrays\n\n\nTo create a basic key:value pair, you need a Header block (top key or Parent key) which is denoted by colon at end\n\n\n    Key:\n    Value\n  \n  ie, \n  \n    Name:\n    \"Joe\" \n\n    # equals  {\"Name\": \"Joe\"}\n\nTo created a nested hash\n\n    Parent Key:\n    child key = child value\n\n    Employee:\n    Name = \"Joe\"\n\n    # equals {\"Employee\": {\"Name\": \"Joe\"}}\n\ndouble quoting non numeric values is recommended to avoid ambiguous value declaration\n\n---\n\n### Basic Dictionary/Hash\n\nTo create a deep hash structure, add a key block declaration of all top keys and a final value, separated by a dot\n\nRio will create all parent subkeys along the path\n\n    first.second.third:\n      fourth = value\n\n  result\n\n    {\n    \"first\": {\n      \"second\": {\n        \"third\": {\n          \"fourth\": \"value\"\n          }\n        }\n      }\n    }\n\ndouble spacing the subkey=value is not mandatory but is recommended for readability, ie\n\n    first.second.third:\n      fourth = value\n\n---\n\n### Escape Character\n\nif the top level key has dot in its name, you can escape parsing it with an escape character '\\\\.'\n\n    first.second\\.level.third:\n      value\n\n  result\n\n    {\n      \"first\": {\n        \"second.level\": {\n          \"third\": \"value\"\n        }\n      }\n    }\n\n---\n\n### Single Key\nIf the Parent key has dots in the name and you want to keep it as single key, double quote the parent key\n\n    \"parent.key.separated.by.dot\":\n    subkey = value\n\n  result\n\n    {\n      \"parent.key.separated.by.dot\": {\n        \"subkey\": \"value\"\n      }\n    }\n\n\n---\n\n### Arrays\n\nTo create an array, declare it using brackets, with each element separated by a comma\n\n    My List:\n      subkey = [first, second, third]\n\n    ## result \n    {\n      \"My List\": {\n        \"subkey\": [\n          \"first\",\n          \"second\",\n          \"third\"\n        ]\n      }\n    }\n\nArrays can also be created using a multiline declaration within a bracket pair\n\n    cars:\n      names = [\n        toyota,\n        ferrari,\n        chevy\n      ]\n\n\n  result\n\n    {\n      \"cars\": {\n        \"names\": [\n          \"toyota\",\n          \"ferrari\",\n          \"chevy\"\n        ]\n      }\n    }\n\nyou can also create an array without a subkey,\n\n    my array:\n      ['a', 'b', 'c']\n\nresult\n\n    {\n      \"my array\": [\n        \"a\",\n        \"b\",\n        \"c\"\n      ]\n    }\n\n\n---\n\n### Child nested subkeys\n\nWith Rio you can also create nested subkeys underneath your parent key, by placing a dot in the subkey declaration\n\n    config.nginx:\n      cache.size = 200\n      cache.limit = 190\n      cache.clean.size = 5\n\nresult \n\n    {\n      \"config\": {\n        \"nginx\": {\n          \"cache\": {\n            \"size\": 200,\n            \"limit\": 190,\n            \"clean\": {\n              \"size\": 5\n            }\n          }\n        }\n      }\n    }\n\nTo treat a child subkey with dots as a single key, wrap it in quotes\n\n    config.nginx:\n      cache.size = 200\n      cache.limit = 190\n      \"cache.clean.size\" = 5\n\n\n---\n\n### Strings, Ints, Booleans, Floats\n\nRio will evaluate each value for its type, ie strings, ints, floats, booleans\n\nBy default, all values are strings, unless its a raw integer. To treat an integer as a string, double quote it\n\n    variables:\n      string = this is a string\n      real int = 12345\n      stringified int = \"12345\"\n      boolean true = True\n      boolean false = False\n      boolean strinfigied = \"True\"\n      float = 2.34596\n\n  result\n\n    {\n      \"variables\": {\n        \"string\": \"this is a string\",\n        \"real int\": 12345,\n        \"stringified int\": \"12345\",\n        \"boolean true\": true,\n        \"boolean false\": false,\n        \"boolean strinfigied\": \"True\",\n        \"float\": 2.34596\n      }\n    }\n\n--- \n\n### Templates\n\nTemplates allow you to reuse configuration data without copying and pasting the same data over and over.\n\nTemplates are created by using the @template keyword\n\n**@template TemplateName:** declares a new template, followed by template variables\n\n**@use** keyword then instructs the key block to use the variables from the given template, ie\n\n    @use = myTemplate\n\n\nfor example, lets say you want to add some Company-specific data to every Employee \n\n(note: double spacing the subkeys is not mandatory but recommended, purely for visual clarity)\n\n    @template company:\n      name = \"Initech\"\n      address = \"123 company drive\"\n      phone = \"200-301-4050\"\n\n    employees.Joe:\n      @use = company\n      department = \"sales\"\n\n    employees.Bill:\n      @use = company\n      department = \"engineering\"\n\n  result:\n\n    {\n      \"employees\": {\n        \"Joe\": {\n          \"name\": \"Initech\",\n          \"address\": \"123 company drive\",\n          \"phone\": \"200-301-4050\",\n          \"department\": \"sales\"\n        },\n        \"Bill\": {\n          \"name\": \"Initech\",\n          \"address\": \"123 company drive\",\n          \"phone\": \"200-301-4050\",\n          \"department\": \"engineering\"\n        }\n      }\n    }\n\nto overwrite a template's variable with a custom value, simply provide a new variable with same name\n\nfor 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\n\n    @template company:\n      name = Initech\n      address = \"123 company drive\"\n      phone = \"200-301-4050\"\n\n    employees.Joe:\n      @use = company\n      department = \"sales\"\n\n    employees.Bill:\n      @use = company\n      department = \"engineering\"\n      phone = \"111-111-1111\"\n\n  result \n\n    {\n      \"employees\": {\n        \"Joe\": {\n          \"name\": \"Initech\",\n          \"address\": \"123 company drive\",\n          \"phone\": \"200-301-4050\",\n          \"department\": \"sales\"\n        },\n        \"Bill\": {\n          \"name\": \"Initech\",\n          \"address\": \"123 company drive\",\n          \"phone\": \"111-111-1111\",\n          \"department\": \"engineering\"\n        }\n      }\n    }\n\nYou can also combine multiple templates in one config block\n\n    @template evens:\n      even_numbers = [2,4,6,8]\n\n    @template odds:\n      odd_numbers = [1,3,5,7]\n\n    @template words:\n      hello = world\n      bunch of words = [\n        sunflower,\n        gunpowder,\n        beer\n      ]\n\n    combined stuff:\n      @use = evens\n      @use = odds\n      @use = words\n\nresult will contain all your template variables\n\n    {\n      \"combined stuff\": {\n        \"even_numbers\": [\n          2,\n          4,\n          6,\n          8\n        ],\n        \"odd_numbers\": [\n          1,\n          3,\n          5,\n          7\n        ],\n        \"hello\": \"world\",\n        \"bunch of words\": [\n          \"sunflower\",\n          \"gunpowder\",\n          \"beer\"\n        ]\n      }\n    }\n\n\n---\n\n### Multiline Comments\n\ncomments or text spanning multiple lines can be written using the single quote troika\n\n    mycomment:\n      comment = '''\n      this \n      is \n      a comment\n      that    spans\n\n      many\n\n      lines\n      '''\n\n  result\n\n    {\n    \"mycomment\": {\n      \"comment\": \"\\nthis \\nis \\na comment\\nthat    spans\\n\\nmany\\n\\nlines\\n\"\n      }\n    }\n\n\n\n---\n\n### Environment Variables\n\nto process a shell environment variable, provide @env flag\n\n    database.credential:\n      password = @env DB_PASSWORD\n\nthis will translate a shell variable $DB_PASSWORD\n\nif the variable is not set, the value will be NULL\n\nto pass a default fallback value if env variable isnt set, provide a default using the double pipe OR symbol\n\n\n\n    database.credential:\n      password = @env DB_PASSWORD || abracadabra123\n\n\nresult\n\n    {\n    \"database\": {\n      \"credential\": {\n        \"password\": \"abracadabra123\"\n        }\n      }\n    }\n\n  \n\n```bash\nexport DB_PASSWORD=\"cheese-is-yummy991\"\n```\n\n\n\n    {\n    \"database\": {\n      \"credential\": {\n        \"password\": \"cheese-is-yummy991\"\n        }\n      }\n    }\n\n\n---\n\n### Comments\n\nComments within the configuration data can be added with # symbol\n\n    # this is a comment\n    key:\n      value  # this is also a comment\n\nComments are not processed during final output\n\n---\n\n### Testing \n\npip install pytest\n\nshell\u003e cd tests\n\nshell\u003e pytest -sv run_tests.py\n\n\n---\n\n### Packaging\n    python3 -m pip install --upgrade pip setuptools wheel build twine\n    python3 -m build\n    python3 -m pip install twine\n    python3 -m twine upload dist/*\n\n## TO DO:\n\n  - add single variables ie $var = joe\n    use var, \n    \n        name = $var\n  \n  - add For loops\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperfecto25%2Frio_config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fperfecto25%2Frio_config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperfecto25%2Frio_config/lists"}