Package: secsie-conf
secsie-confpip3 install secsie-confSecsie 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 isFARbetter than a lot of other things you could use (cough cough XML)), you can save time writing your config files insecsie.Thesecsielanguage format is very similar toini, except just a little better. You can usesecsie-confto read.inifiles into Pythondicts.secsie-confwill NOT write.inifiles however, at least at this stage.I also wrote a version for Java, which is available atgithub.com/noahbroyles/secsie-java. You can use it to parse.propertiesfiles. Minecraft will probably adopt this in the next few months for theirserver.properties;)Advantages over JSON:easier to readfaster and more natural to writeno special syntax required for strings vs ints, floats, bools, etc.file size usually smaller than readable JSONSecsie Language ConstructsThese are the rules of the secsie config language:Comment lines begin with#or;, but inline comments can only begin with the octothorpe (#) andmusthave a space preceding them.Whitespace is ignored everywhere except in key names and section tag names.A config file consists of sections and attributes(keys and values).A section ends where the next section begins. Attributes declared before sections begin are valid.To begin a section use the following syntax:[section1]# attribute lines in this section followThe syntax for an attribute line is:key=valueSpaces are not allowed in key names or section tags. Onlya-z(case insensitive),0-9,_, and-are allowed in section tag names, while other special charactersareallowed in key names.Values can consist of any character except#. Leading and trailing whitespace is removed. String values separated by commas are interpreted as lists.INIsecsie-confcan be used to read.inifiles, as long as the modeiniis specifed to the parser. The rules of interpretation for.inifiles vary slightly.Differences:Section names are allowed to contain spaces and dashesquoted strings are valid, but the quotes are removed (there is no need to quote string insecsie;)Lists in.inifiles can have a trailing comma with no effect, but a trailing comma insecsiewill create a blank stringsecsie-confcanNOTbe used to write.inifiles. You can read an.inifile and output it in validsecsie, but you cannot expect valid.inioutput.Valid valuesSecsie 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 valuestring_key=whatever value you wantInts:numb=42# Automatically converted to int when parsedFloats:pi=3.14159265# Automatically converted to float when parsedNull type (None):# 'null' is used as the NoneType (case insensitive)nothing=nullBooleans:# True and yes are truthy values (case insensitive)truth=truetruth2=Truetruth3=yes# False and no are falsy values (case insensitive)untruth=falsEuntruth2=Falseuntruth3=noLists:# To interpret a value as a list, you must separate the list values with a comma.list=this, that, the otherExamplesexamples/valid.secsie.conf:; This is an example of a valid secsie filebefore_section=totally okay# Whitespace don't matter; Here are examples of how types are interpreted(no keywords are off limits!)[special_values]int=42float=269.887truth=yesfalsehood=notrue=true; I don't encourage this but it's valid ;)false=FaLSe# this following will be interpreted as a listcoolKids=jim, bill, bob, alice, 42# Null valuenah=Null[anotherSection]# The indent here is optional, included for readabilitysections=are amazingParse 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 UsageRead asecsieconfig file as adict:importjsonimportsecsie# To get a dict from a config fileconfig=secsie.parse_config_file('examples/valid.secsie.conf')print(json.dumps(config,indent=2))# For prettynessResult:{"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.inifile:importjsonimportsecsie# 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 955secsie.InvalidSyntax: Invalid syntax on line 955: "[CLI Server]" - bad section descriptor or value assignmentWe can see that this up and broke. WTF?! Actually, it's okay. Spaces aren't allowed insecsiesection names, remember? When reading an.inifile, we need to pass the argumentmode='ini'to theparse_config_filefunction, 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 somesexysecsie JSON!Write asecsiefile:Now that we have thephp.inicontents stored inconfig, let's output it insecsie!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=Onshort_open_tag=Offprecision=14output_buffering=4096zlib.output_compression=Offimplicit_flush=Off;	unserialize_callback_func =serialize_precision=-1disable_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=Onzend.exception_ignore_args=Onexpose_php=Offmax_execution_time=30max_input_time=60memory_limit=128Merror_reporting=E_ALL & ~E_DEPRECATED & ~E_STRICTdisplay_errors=Offdisplay_startup_errors=Offlog_errors=Onlog_errors_max_len=1024ignore_repeated_errors=Offignore_repeated_source=Offreport_memleaks=Onvariables_order=GPCSrequest_order=GPregister_argc_argv=Offauto_globals_jit=Onpost_max_size=8M;	auto_prepend_file =;	auto_append_file =default_mimetype=text/htmldefault_charset=UTF-8;	doc_root =;	user_dir =enable_dl=Offfile_uploads=Onupload_max_filesize=2Mmax_file_uploads=20allow_url_fopen=Onallow_url_include=Offdefault_socket_timeout=60[CLIServer]cli_server.color=On[Pdo_mysql];	pdo_mysql.default_socket =[mailfunction]SMTP=localhostsmtp_port=25mail.add_x_header=Off[ODBC]odbc.allow_persistent=Onodbc.check_persistent=Onodbc.max_persistent=-1odbc.max_links=-1odbc.defaultlrl=4096odbc.defaultbinmode=1[MySQLi]mysqli.max_persistent=-1mysqli.allow_persistent=Onmysqli.max_links=-1mysqli.default_port=3306;	mysqli.default_socket =;	mysqli.default_host =;	mysqli.default_user =;	mysqli.default_pw =mysqli.reconnect=Off[mysqlnd]mysqlnd.collect_statistics=Onmysqlnd.collect_memory_statistics=Off[PostgreSQL]pgsql.allow_persistent=Onpgsql.auto_reset_persistent=Offpgsql.max_persistent=-1pgsql.max_links=-1pgsql.ignore_notice=0pgsql.log_notice=0[bcmath]bcmath.scale=0[Session]session.save_handler=filessession.use_strict_mode=0session.use_cookies=1session.use_only_cookies=1session.name=PHPSESSIDsession.auto_start=0session.cookie_lifetime=0session.cookie_path=/;	session.cookie_domain =;	session.cookie_httponly =;	session.cookie_samesite =session.serialize_handler=phpsession.gc_probability=0session.gc_divisor=1000session.gc_maxlifetime=1440;	session.referer_check =session.cache_limiter=nocachesession.cache_expire=180session.use_trans_sid=0session.sid_length=26session.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=1soap.wsdl_cache_dir=/tmpsoap.wsdl_cache_ttl=86400soap.wsdl_cache_limit=5[ldap]ldap.max_links=-1You should notice 2 things:Keys and value assignments are separated by an equals sign with a space ON BOTH SIDES!key = value,NOTkey=value. That is ugly and lazy. This ain't minified JS, son.They make things for that...Blank values were commented out. If you disagree with that,MAKE 'EM NULL!key =doesn't say anything.