Skip to main content

A small library for parsing configuration files

Project description

secsie-conf

PyPi Deployment Unit Tests

pip3 install secsie-conf

Secsie is a configuration language parser for Python, made for speed and beauty. Instead of writing config files in JSON (don't get me wrong, JSON is FAR better than a lot of other things you could use (cough cough XML)), you can save time writing your config files in secsie.
The secsie language format is very similar to ini, except just a little better. You can use secsie-conf to read .ini files into Python dicts. secsie-conf will NOT write .ini files however, at least at this stage.

Advantages over JSON:

  • easier to read
  • faster and more natural to write
  • no special syntax required for strings vs ints, floats, bools, etc.
  • file size usually smaller than readable JSON

Secsie Language Constructs

These are the rules of the secsie config language:

  1. Comment lines begin with # or ;, but inline comments can only begin with the octothorpe (#) and must have a space preceding them.
  2. Whitespace is ignored everywhere except in key names and section tag names.
  3. A config file consists of sections and attributes(keys and values).
  4. A section ends where the next section begins. Attributes declared before sections begin are valid.
  5. To begin a section use the following syntax:
[section1]
# attribute lines in this section follow
  1. The syntax for an attribute line is:
key = value
  1. Spaces are not allowed in key names or section tags. Only a-z(case insensitive), 0-9, _, and - are allowed in section tag names, while other special characters are allowed in key names.
  2. Values can consist of any character except #. Leading and trailing whitespace is removed. String values separated by commas are interpreted as lists.

INI

secsie-conf can be used to read .ini files, as long as the mode ini is specifed to the parser. The rules of interpretation for .ini files vary slightly.

Differences:

  • Section names are allowed to contain spaces and dashes
  • quoted strings are valid, but the quotes are removed (there is no need to quote string in secsie ;)
  • Lists in .ini files can have a trailing comma with no effect, but a trailing comma in secsie will create a blank string
    secsie-conf can NOT be used to write .ini files. You can read an .ini file and output it in valid secsie, but you cannot expect valid .ini output.

Valid values

Secsie supports strings, ints, floats, null types, booleans, and lists. Most of these types can be written out by themselves and will automatically be converted to the appropriate native type. Lists require comma separation.

Strings:

# Spaces are allowed in string value
string_key = whatever value you want

Ints:

numb = 42  # Automatically converted to int when parsed

Floats:

pi = 3.14159265  # Automatically converted to float when parsed

Null type (None):

# 'null' is used as the NoneType (case insensitive)
nothing = null

Booleans:

# True and yes are truthy values (case insensitive)
truth = true
truth2 = True
truth3 = yes
# False and no are falsy values (case insensitive)
untruth = falsE
untruth2 = False
untruth3 = no

Lists:

# To interpret a value as a list, you must separate the list values with a comma.
list = this, that, the other

Examples

examples/valid.secsie.conf:

; This is an example of a valid secsie file

before_section = totally okay

# Whitespace don't matter

; Here are examples of how types are interpreted(no keywords are off limits!)
[special_values]
    int = 42
    float = 269.887
    truth = yes
    falsehood = no
    true = true
    ; I don't encourage this but it's valid ;)
    false = FaLSe
    
    # this following will be interpreted as a list
    coolKids = jim, bill, bob, alice, 42
    
    # Null value
    nah = Null

[anotherSection]
    # The indent here is optional, included for readability
    sections = are amazing

Parse result:

{'before_section': 'totally okay', 'special_values': {'int': 42, 'float': 269.887, 'truth': True, 'falsehood': False, 'true': True, 'false': False, 'coolKids': ['jim', 'bill', 'bob', 'alice', 42], 'nah': None}, 'anotherSection': {'sections': 'are amazing'}}

Module Usage

Read a secsie config file as a dict:

import json
import secsie

# To get a dict from a config file
config = secsie.parse_config_file('examples/valid.secsie.conf')
print(json.dumps(config, indent=2))  # For prettyness

Result:

{
  "before_section": "totally okay",
  "special_values": {
    "int": 42,
    "float": 269.887,
    "truth": true,
    "falsehood": false,
    "true": true,
    "false": false,
    "coolKids": [
      "jim",
      "bill",
      "bob",
      "alice",
      42
    ],
    "nah": null
  },
  "anotherSection": {
    "sections": "are amazing"
  }
}

Read an .ini file:

import json
import secsie

# This might not work...
config = secsie.parse_config_file('examples/php.ini')

Result:

Traceback (most recent call last):
  ...
  File "/Users/nbroyles/PycharmProjects/secsie-conf/secsie/__init__.py", line 90, in _write_to_conf_
    raise InvalidSyntax(f'"{line}" - bad section descriptor or value assignment', line_number)
  File "<string>", line 955
secsie.InvalidSyntax: Invalid syntax on line 955: "[CLI Server]" - bad section descriptor or value assignment

We can see that this up and broke. WTF?! Actually, it's okay. Spaces aren't allowed in secsie section names, remember? When reading an .ini file, we need to pass the argument mode='ini' to the parse_config_file function, like this:

config = secsie.parse_config_file('examples/php.ini', mode='ini')
print(json.dumps(config, indent=2))
{
  "PHP": {
    "engine": "On",
    "short_open_tag": "Off",
    "precision": 14,
    "output_buffering": 4096,
    "zlib.output_compression": "Off",
    "implicit_flush": "Off",
    "unserialize_callback_func": "",
    "serialize_precision": -1,
    "disable_functions": [
      "pcntl_alarm",
      "pcntl_fork",
      "pcntl_waitpid",
      "pcntl_wait",
      "pcntl_wifexited",
      "pcntl_wifstopped",
      "pcntl_wifsignaled",
      "pcntl_wifcontinued",
      "pcntl_wexitstatus",
      "pcntl_wtermsig",
      "pcntl_wstopsig",
      "pcntl_signal",
      "pcntl_signal_get_handler",
      "pcntl_signal_dispatch",
      "pcntl_get_last_error",
      "pcntl_strerror",
      "pcntl_sigprocmask",
      "pcntl_sigwaitinfo",
      "pcntl_sigtimedwait",
      "pcntl_exec",
      "pcntl_getpriority",
      "pcntl_setpriority",
      "pcntl_async_signals",
      "pcntl_unshare"
    ],
    "disable_classes": "",
    "zend.enable_gc": "On",
    "zend.exception_ignore_args": "On",
    "expose_php": "Off",
    "max_execution_time": 30,
    "max_input_time": 60,
    "memory_limit": "128M",
    "error_reporting": "E_ALL & ~E_DEPRECATED & ~E_STRICT",
    "display_errors": "Off",
    "display_startup_errors": "Off",
    "log_errors": "On",
    "log_errors_max_len": 1024,
    "ignore_repeated_errors": "Off",
    "ignore_repeated_source": "Off",
    "report_memleaks": "On",
    "variables_order": "GPCS",
    "request_order": "GP",
    "register_argc_argv": "Off",
    "auto_globals_jit": "On",
    "post_max_size": "8M",
    "auto_prepend_file": "",
    "auto_append_file": "",
    "default_mimetype": "text/html",
    "default_charset": "UTF-8",
    "doc_root": "",
    "user_dir": "",
    "enable_dl": "Off",
    "file_uploads": "On",
    "upload_max_filesize": "2M",
    "max_file_uploads": 20,
    "allow_url_fopen": "On",
    "allow_url_include": "Off",
    "default_socket_timeout": 60
  },
  "CLI Server": {
    "cli_server.color": "On"
  },
  "Pdo_mysql": {
    "pdo_mysql.default_socket": ""
  },
  "mail function": {
    "SMTP": "localhost",
    "smtp_port": 25,
    "mail.add_x_header": "Off"
  },
  "ODBC": {
    "odbc.allow_persistent": "On",
    "odbc.check_persistent": "On",
    "odbc.max_persistent": -1,
    "odbc.max_links": -1,
    "odbc.defaultlrl": 4096,
    "odbc.defaultbinmode": 1
  },
  "MySQLi": {
    "mysqli.max_persistent": -1,
    "mysqli.allow_persistent": "On",
    "mysqli.max_links": -1,
    "mysqli.default_port": 3306,
    "mysqli.default_socket": "",
    "mysqli.default_host": "",
    "mysqli.default_user": "",
    "mysqli.default_pw": "",
    "mysqli.reconnect": "Off"
  },
  "mysqlnd": {
    "mysqlnd.collect_statistics": "On",
    "mysqlnd.collect_memory_statistics": "Off"
  },
  "PostgreSQL": {
    "pgsql.allow_persistent": "On",
    "pgsql.auto_reset_persistent": "Off",
    "pgsql.max_persistent": -1,
    "pgsql.max_links": -1,
    "pgsql.ignore_notice": 0,
    "pgsql.log_notice": 0
  },
  "bcmath": {
    "bcmath.scale": 0
  },
  "Session": {
    "session.save_handler": "files",
    "session.use_strict_mode": 0,
    "session.use_cookies": 1,
    "session.use_only_cookies": 1,
    "session.name": "PHPSESSID",
    "session.auto_start": 0,
    "session.cookie_lifetime": 0,
    "session.cookie_path": "/",
    "session.cookie_domain": "",
    "session.cookie_httponly": "",
    "session.cookie_samesite": "",
    "session.serialize_handler": "php",
    "session.gc_probability": 0,
    "session.gc_divisor": 1000,
    "session.gc_maxlifetime": 1440,
    "session.referer_check": "",
    "session.cache_limiter": "nocache",
    "session.cache_expire": 180,
    "session.use_trans_sid": 0,
    "session.sid_length": 26,
    "session.trans_sid_tags": [
      "a=href",
      "area=href",
      "frame=src",
      "form="
    ],
    "session.sid_bits_per_character": 5
  },
  "Assertion": {
    "zend.assertions": -1
  },
  "Tidy": {
    "tidy.clean_output": "Off"
  },
  "soap": {
    "soap.wsdl_cache_enabled": 1,
    "soap.wsdl_cache_dir": "/tmp",
    "soap.wsdl_cache_ttl": 86400,
    "soap.wsdl_cache_limit": 5
  },
  "ldap": {
    "ldap.max_links": -1
  }
}

That ^'s a whole PHP configuration file converted to some sexy secsie JSON!

Write a secsie file:

Now that we have the php.ini contents stored in config, let's output it in secsie!

secsie.generate_config_file(config, output_file='examples/php_ini.secsie.conf')

Output (examples/php_ini.secsie.conf):

# php_ini.secsie.conf auto-generated by secsie

[PHP]
	engine = On
	short_open_tag = Off
	precision = 14
	output_buffering = 4096
	zlib.output_compression = Off
	implicit_flush = Off
;	unserialize_callback_func = 
	serialize_precision = -1
	disable_functions = pcntl_alarm, pcntl_fork, pcntl_waitpid, pcntl_wait, pcntl_wifexited, pcntl_wifstopped, pcntl_wifsignaled, pcntl_wifcontinued, pcntl_wexitstatus, pcntl_wtermsig, pcntl_wstopsig, pcntl_signal, pcntl_signal_get_handler, pcntl_signal_dispatch, pcntl_get_last_error, pcntl_strerror, pcntl_sigprocmask, pcntl_sigwaitinfo, pcntl_sigtimedwait, pcntl_exec, pcntl_getpriority, pcntl_setpriority, pcntl_async_signals, pcntl_unshare
;	disable_classes = 
	zend.enable_gc = On
	zend.exception_ignore_args = On
	expose_php = Off
	max_execution_time = 30
	max_input_time = 60
	memory_limit = 128M
	error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
	display_errors = Off
	display_startup_errors = Off
	log_errors = On
	log_errors_max_len = 1024
	ignore_repeated_errors = Off
	ignore_repeated_source = Off
	report_memleaks = On
	variables_order = GPCS
	request_order = GP
	register_argc_argv = Off
	auto_globals_jit = On
	post_max_size = 8M
;	auto_prepend_file = 
;	auto_append_file = 
	default_mimetype = text/html
	default_charset = UTF-8
;	doc_root = 
;	user_dir = 
	enable_dl = Off
	file_uploads = On
	upload_max_filesize = 2M
	max_file_uploads = 20
	allow_url_fopen = On
	allow_url_include = Off
	default_socket_timeout = 60


[CLIServer]
	cli_server.color = On


[Pdo_mysql]
;	pdo_mysql.default_socket = 


[mailfunction]
	SMTP = localhost
	smtp_port = 25
	mail.add_x_header = Off


[ODBC]
	odbc.allow_persistent = On
	odbc.check_persistent = On
	odbc.max_persistent = -1
	odbc.max_links = -1
	odbc.defaultlrl = 4096
	odbc.defaultbinmode = 1


[MySQLi]
	mysqli.max_persistent = -1
	mysqli.allow_persistent = On
	mysqli.max_links = -1
	mysqli.default_port = 3306
;	mysqli.default_socket = 
;	mysqli.default_host = 
;	mysqli.default_user = 
;	mysqli.default_pw = 
	mysqli.reconnect = Off


[mysqlnd]
	mysqlnd.collect_statistics = On
	mysqlnd.collect_memory_statistics = Off


[PostgreSQL]
	pgsql.allow_persistent = On
	pgsql.auto_reset_persistent = Off
	pgsql.max_persistent = -1
	pgsql.max_links = -1
	pgsql.ignore_notice = 0
	pgsql.log_notice = 0


[bcmath]
	bcmath.scale = 0


[Session]
	session.save_handler = files
	session.use_strict_mode = 0
	session.use_cookies = 1
	session.use_only_cookies = 1
	session.name = PHPSESSID
	session.auto_start = 0
	session.cookie_lifetime = 0
	session.cookie_path = /
;	session.cookie_domain = 
;	session.cookie_httponly = 
;	session.cookie_samesite = 
	session.serialize_handler = php
	session.gc_probability = 0
	session.gc_divisor = 1000
	session.gc_maxlifetime = 1440
;	session.referer_check = 
	session.cache_limiter = nocache
	session.cache_expire = 180
	session.use_trans_sid = 0
	session.sid_length = 26
	session.trans_sid_tags = a=href, area=href, frame=src, form=
	session.sid_bits_per_character = 5


[Assertion]
	zend.assertions = -1


[Tidy]
	tidy.clean_output = Off


[soap]
	soap.wsdl_cache_enabled = 1
	soap.wsdl_cache_dir = /tmp
	soap.wsdl_cache_ttl = 86400
	soap.wsdl_cache_limit = 5


[ldap]
	ldap.max_links = -1

You should notice 2 things:

  1. Keys and value assignments are separated by an equals sign with a space ON BOTH SIDES! key = value, NOT key=value. That is ugly and lazy. This ain't minified JS, son. They make things for that...
  2. Blank values were commented out. If you disagree with that, MAKE 'EM NULL! key = doesn't say anything.

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

secsie_conf-3.1.4.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

secsie_conf-3.1.4-py3-none-any.whl (10.8 kB view details)

Uploaded Python 3

File details

Details for the file secsie_conf-3.1.4.tar.gz.

File metadata

  • Download URL: secsie_conf-3.1.4.tar.gz
  • Upload date:
  • Size: 17.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for secsie_conf-3.1.4.tar.gz
Algorithm Hash digest
SHA256 ca771cd75305625b34194697b896769aec9a84c8f06a09af1cf547cd9da4e477
MD5 8407daa7e61777dee559bed5ad5aeb01
BLAKE2b-256 ae5676b09becceb7e3d003138702704d71f640894f6482c3d3b9804cd5470e36

See more details on using hashes here.

File details

Details for the file secsie_conf-3.1.4-py3-none-any.whl.

File metadata

  • Download URL: secsie_conf-3.1.4-py3-none-any.whl
  • Upload date:
  • Size: 10.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for secsie_conf-3.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 b2e5994fd4fcd23f42bb57589b13e1817e3d12a63d0ad5263145f4359e29fb4a
MD5 547c9f81e8e2ee87fb671d45377e7434
BLAKE2b-256 381fc2487014699a9784ba4e2658a9b7614a60d3e1db80b8ba2cd7b7ed2b38ab

See more details on using hashes here.

Supported by

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