DEV
- implement delete section /keys - implement comment support - implement array / mixed mode return - implement strict mode - more unittest
This commit is contained in:
3
.settings/org.eclipse.core.resources.prefs
Normal file
3
.settings/org.eclipse.core.resources.prefs
Normal file
@@ -0,0 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//ChaChaSimpleINI/core.py=UTF-8
|
||||
encoding/<project>=UTF-8
|
||||
@@ -11,7 +11,8 @@ work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
from ._version import __version__
|
||||
|
||||
from .core import ChaChaINI_KeyNotFoundException, \
|
||||
ChaChaINI_SectionNotFoundException
|
||||
ChaChaINI_SectionNotFoundException, \
|
||||
ChaChaINI_WrongFormatException
|
||||
|
||||
from .core import ChaChaSimpleINI_key, \
|
||||
ChaChaSimpleINI_section, \
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
"""
|
||||
ChaChaSimpleINI (c) by clement chastanier
|
||||
ChaChaSimpleINI (c) by Clément CHASTANIER
|
||||
|
||||
ChaChaSimpleINI is licensed under a
|
||||
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
|
||||
You should have received a copy of the license along with this
|
||||
work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
ChaChaSimpleINI is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
|
||||
You should have received a copy of the license along with this work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
|
||||
"""
|
||||
|
||||
import re
|
||||
import os.path
|
||||
from typing import Union
|
||||
@@ -16,75 +14,325 @@ class ChaChaINI_KeyNotFoundException(RuntimeError):
|
||||
|
||||
class ChaChaINI_SectionNotFoundException(RuntimeError):
|
||||
pass
|
||||
|
||||
class ChaChaSimpleINI_key:
|
||||
|
||||
class ChaChaINI_WrongFormatException(RuntimeError):
|
||||
pass
|
||||
|
||||
class ChaChaSimpleINI_key_Base:
|
||||
pass
|
||||
|
||||
class ChaChaSimpleINI_key_Blank(ChaChaSimpleINI_key_Base):
|
||||
pass
|
||||
|
||||
class ChaChaSimpleINI_key_Comment(ChaChaSimpleINI_key_Base):
|
||||
def __init__(self,value:str):
|
||||
"""
|
||||
Create a new Key-Comment object
|
||||
|
||||
:param str value: Comment-line value
|
||||
:return: The Key Comment value
|
||||
:rtype: ChaChaSimpleINI_key_Comment
|
||||
"""
|
||||
super().__init__()
|
||||
self.value = value
|
||||
|
||||
def format(self) -> str:
|
||||
return ";" + self.value
|
||||
|
||||
|
||||
class ChaChaSimpleINI_key(ChaChaSimpleINI_key_Base):
|
||||
def __init__(self,name:str,value:str):
|
||||
"""
|
||||
Create a new Key object
|
||||
|
||||
:param str name: Key's name
|
||||
:param str value: Key's value
|
||||
:return: The Key
|
||||
:rtype: ChaChaSimpleINI_key
|
||||
"""
|
||||
self.name = name
|
||||
self.value = value
|
||||
#print("add key with value: {0}".format(self.value))
|
||||
|
||||
def format(self,bBeautify:bool = False) -> str:
|
||||
"""
|
||||
Output the formated Key's value: example: KeyName = KeyValue
|
||||
|
||||
:param bool bBeautify: enable space arround '='
|
||||
:return: formated string
|
||||
:rtype: str
|
||||
"""
|
||||
if bBeautify:
|
||||
return "{0} = {1}".format(self.name,self.value)
|
||||
else:
|
||||
return "{0}={1}".format(self.name,self.value)
|
||||
|
||||
class ChaChaSimpleINI_section:
|
||||
def __init__(self,name:str):
|
||||
|
||||
|
||||
class ChaChaSimpleINI_section_Base:
|
||||
pass
|
||||
|
||||
class ChaChaSimpleINI_section_Blank(ChaChaSimpleINI_section_Base):
|
||||
pass
|
||||
|
||||
class ChaChaSimpleINI_section_Comment(ChaChaSimpleINI_section_Base):
|
||||
def __init__(self,value:str):
|
||||
"""
|
||||
Create a new Section-Comment object
|
||||
|
||||
:param str value: comment-line value
|
||||
:return: The Section Comment value
|
||||
:rtype: ChaChaSimpleINI_section_Comment
|
||||
"""
|
||||
super().__init__()
|
||||
self.value = value
|
||||
|
||||
def formatAll(self) -> str:
|
||||
return ";" + self.value
|
||||
|
||||
|
||||
|
||||
class ChaChaSimpleINI_section(ChaChaSimpleINI_section_Base):
|
||||
def __init__(self,name:str,bForceAlwaysOutputArrays:bool = False):
|
||||
"""
|
||||
Create a new Section object
|
||||
|
||||
:param str name: Key's name
|
||||
:param bool bForceAlwaysOutputArrays: Force API to always return an array even with one single Key/Section
|
||||
:return: The Section
|
||||
:rtype: ChaChaSimpleINI_section
|
||||
"""
|
||||
super().__init__()
|
||||
self.name = name
|
||||
self.bForceAlwaysOutputArrays = bForceAlwaysOutputArrays
|
||||
self.ar_keys=[]
|
||||
|
||||
def format(self) -> str:
|
||||
"""
|
||||
Output the formated Section's value, example: [Section Name]
|
||||
|
||||
:return: formated string
|
||||
:rtype: str
|
||||
"""
|
||||
return "[{0}]".format(self.name)
|
||||
|
||||
def formatAll(self,bBeautify:bool = False) -> str:
|
||||
"""
|
||||
Output the full formated Section's.
|
||||
Example:
|
||||
[Section Name]
|
||||
Key1Name = Key1Value
|
||||
Key2Name = Key2Value
|
||||
...
|
||||
|
||||
:param bool bBeautify: enable space arround '='
|
||||
:return: formated string
|
||||
:rtype: str
|
||||
"""
|
||||
if self.name =="[]":
|
||||
return ""
|
||||
result = self.format() + "\n"
|
||||
for key in self.ar_keys:
|
||||
result = result + key.format(bBeautify) + "\n"
|
||||
if(isinstance(key,ChaChaSimpleINI_key)):
|
||||
result = result + key.format(bBeautify) + "\n"
|
||||
elif(isinstance(key,ChaChaSimpleINI_key_Comment)):
|
||||
result = result + key.format()+ "\n"
|
||||
elif(isinstance(key,ChaChaSimpleINI_key_Blank)):
|
||||
result = result + "\n"
|
||||
return result
|
||||
|
||||
def appendCommentKey(self,value:str):
|
||||
key = ChaChaSimpleINI_key_Comment(value)
|
||||
self.ar_keys.append(key)
|
||||
return key
|
||||
|
||||
def appendBlankKey(self):
|
||||
key = ChaChaSimpleINI_key_Blank()
|
||||
self.ar_keys.append(key)
|
||||
return key
|
||||
|
||||
def appendKey(self,name:str,value:str) -> None:
|
||||
"""
|
||||
Create and Add a new Key to the Section.
|
||||
|
||||
def appendKey(self,name,value) -> None:
|
||||
:param str name: Name of the new Key
|
||||
:param str value: Value of the new Key
|
||||
:return: Nothing
|
||||
:rtype: None
|
||||
"""
|
||||
key = ChaChaSimpleINI_key(name,value)
|
||||
self.ar_keys.append(key)
|
||||
#print("add key {0} in {1}".format(name,self.name))
|
||||
return key
|
||||
|
||||
def getAllKeyNames(self)->list[str]:
|
||||
"""
|
||||
Return all Key names of the current Section
|
||||
|
||||
:return: List of Key's name
|
||||
:rtype: list[str]
|
||||
"""
|
||||
result=[]
|
||||
for key in self.ar_keys:
|
||||
result.append(key.name)
|
||||
if(isinstance(key,ChaChaSimpleINI_key)):
|
||||
result.append(key.name)
|
||||
return result
|
||||
|
||||
def delKey(self,name:str,index:int = None,value:str = None) -> None:
|
||||
"""
|
||||
Delete an existing Key from section.
|
||||
If index is set, this filter will be applied.
|
||||
If value is set, this filter will be applied.
|
||||
Both filter can be enabled together.
|
||||
An exception will be raised if the Key isn't found.
|
||||
|
||||
def getKey(self,name:str) -> Union[ChaChaSimpleINI_key,list[ChaChaSimpleINI_key]]:
|
||||
result = None
|
||||
:param str name: The Key name
|
||||
:param index: The Key instance index (in case of multiple Key with same name)
|
||||
:param value: The Key value to delete (in case of multiple Key with same name)
|
||||
:type index: int or None
|
||||
:type value: str or None
|
||||
:return: Number of deleted keys
|
||||
:rtype: int
|
||||
:raises ChaChaINI_KeyNotFoundException
|
||||
"""
|
||||
keys = self.getKey(name)
|
||||
if isinstance(keys,ChaChaSimpleINI_key):
|
||||
_keys = []
|
||||
_keys.append(keys)
|
||||
keys=_keys
|
||||
i = 0
|
||||
ndeleted = 0
|
||||
for key in keys:
|
||||
if(isinstance(key,ChaChaSimpleINI_key)):
|
||||
indexok = True
|
||||
valueok = True
|
||||
if index is not None:
|
||||
indexok = False
|
||||
if index == i:
|
||||
indexok = True
|
||||
if value is not None:
|
||||
valueok = False
|
||||
if value == key.value:
|
||||
valueok = True
|
||||
if indexok and valueok:
|
||||
self.ar_keys.remove(key)
|
||||
ndeleted = ndeleted + 1
|
||||
i = i + 1
|
||||
|
||||
if ndeleted == 0:
|
||||
raise ChaChaINI_KeyNotFoundException()
|
||||
|
||||
return ndeleted
|
||||
|
||||
def getKeyEx(self,name:str,index:int = None,value:str = None) -> Union[ChaChaSimpleINI_key,list[ChaChaSimpleINI_key]]:
|
||||
"""
|
||||
Get one or more Key from Section (Extended).
|
||||
If index is set, this filter will be applied.
|
||||
If value is set, this filter will be applied.
|
||||
Both filter can be enabled together.
|
||||
An exception will be raised if the Key isn't found.
|
||||
|
||||
:param str name: The Key name
|
||||
:param index: The Key instance index (in case of multiple Key with same name)
|
||||
:param value: The Key value to delete (in case of multiple Key with same name)
|
||||
:type index: int or None
|
||||
:type value: str or None
|
||||
:return: Found Keys
|
||||
:rtype: ChaChaSimpleINI_key or list[ChaChaSimpleINI_key]
|
||||
:raises ChaChaINI_KeyNotFoundException
|
||||
"""
|
||||
if self.bForceAlwaysOutputArrays:
|
||||
result = []
|
||||
else:
|
||||
result = None
|
||||
i=0
|
||||
for key in self.ar_keys:
|
||||
if name == key.name:
|
||||
if result is None:
|
||||
result = key
|
||||
#print("value found ({0})".format(key.value))
|
||||
elif isinstance(result,ChaChaSimpleINI_key):
|
||||
result = [result,key]
|
||||
#print("another value found, switching to composed value")
|
||||
else: #array
|
||||
result.append(key)
|
||||
#print("another value found, add to result array")
|
||||
if(isinstance(key,ChaChaSimpleINI_key)):
|
||||
indexok = True
|
||||
valueok = True
|
||||
if name == key.name:
|
||||
if index is not None:
|
||||
indexok = False
|
||||
if index == i:
|
||||
indexok = True
|
||||
if value is not None:
|
||||
valueok = False
|
||||
if value == key.value:
|
||||
valueok = True
|
||||
if indexok and valueok:
|
||||
if self.bForceAlwaysOutputArrays:
|
||||
result.append(key)
|
||||
else:
|
||||
if result is None:
|
||||
result = key
|
||||
elif isinstance(result,ChaChaSimpleINI_key):
|
||||
result = [result,key]
|
||||
else: #array
|
||||
result.append(key)
|
||||
if result is None:
|
||||
raise ChaChaINI_KeyNotFoundException()
|
||||
return result
|
||||
|
||||
def getKey(self,name:str) -> Union[ChaChaSimpleINI_key,list[ChaChaSimpleINI_key]]:
|
||||
"""
|
||||
Get one or more Key from Section.
|
||||
An exception will be raised if the Key isn't found.
|
||||
|
||||
def getKeyValue(self,name:str) -> Union[str,list[str]]:
|
||||
keys = self.getKey(name)
|
||||
:param str name: The key name
|
||||
:return: Found Keys
|
||||
:rtype: ChaChaSimpleINI_key or list[ChaChaSimpleINI_key]
|
||||
:raises ChaChaINI_KeyNotFoundException
|
||||
"""
|
||||
return self.getKeyEx(name,None,None)
|
||||
|
||||
def getKeyValueEx(self,name:str,index:int = None,value:str = None) -> Union[str,list[str]]:
|
||||
"""
|
||||
Get one or more Key's values from Section (Extended).
|
||||
If index is set, this filter will be applied.
|
||||
If value is set, this filter will be applied.
|
||||
Both filter can be enabled together.
|
||||
An exception will be raised if the Key isn't found.
|
||||
|
||||
:param str name: The Key name
|
||||
:param index: The Key instance index (in case of multiple Key with same name)
|
||||
:param value: The Key value to delete (in case of multiple Key with same name)
|
||||
:type index: int or None
|
||||
:type value: str or None
|
||||
:return: Found Key's values
|
||||
:rtype: str or list[str]
|
||||
:raises ChaChaINI_KeyNotFoundException
|
||||
"""
|
||||
keys = self.getKeyEx(name,index,value)
|
||||
if isinstance(keys,ChaChaSimpleINI_key):
|
||||
#print("a")
|
||||
return keys.value
|
||||
else: #array
|
||||
#print("b")
|
||||
result = []
|
||||
for key in keys:
|
||||
result.append(key.value)
|
||||
if(isinstance(key,ChaChaSimpleINI_key)):
|
||||
result.append(key.value)
|
||||
return result
|
||||
|
||||
def getKeyValue(self,name:str) -> Union[str,list[str]]:
|
||||
"""
|
||||
Get one or more Key's values from Section.
|
||||
An exception will be raised if the Key isn't found.
|
||||
|
||||
def setAddKeyValue(self,name:str,value:str,bForceAddKey:bool = False) -> Union[str,list[str]]:
|
||||
:param str name: The Key name
|
||||
:return: Found Key's values
|
||||
:rtype: str or list[str]
|
||||
:raises ChaChaINI_KeyNotFoundException
|
||||
"""
|
||||
return self.getKeyValueEx(name,None,None)
|
||||
|
||||
def setAddKeyValue(self,name:str,value:str,bForceAddKey:bool = False) -> None:
|
||||
"""
|
||||
Set or Add a new key with value.
|
||||
|
||||
:param str name: Key's name
|
||||
:param str value: Key's value
|
||||
:param bool bForceAddKey: Force to add a new Key, even if then name allready exists
|
||||
:return: Nothing
|
||||
:rtype: None
|
||||
:raises
|
||||
"""
|
||||
if bForceAddKey:
|
||||
keys = self.appendKey(name,'')
|
||||
else:
|
||||
@@ -97,107 +345,332 @@ class ChaChaSimpleINI_section:
|
||||
keys.value = value
|
||||
else: #array: in this case we set value of the last key
|
||||
keys[-1].value = value
|
||||
|
||||
class ChaChaSimpleINI_section_Root(ChaChaSimpleINI_section):
|
||||
def __init__(self,bForceAlwaysOutputArrays:bool = False):
|
||||
super().__init__("[]",bForceAlwaysOutputArrays)
|
||||
|
||||
class ChaChaSimpleINI:
|
||||
def __init__(self,filepath:str = None):
|
||||
def __init__(self,filepath:str = None,bForceAlwaysOutputArrays:bool = False,bStrict:bool = False):
|
||||
"""
|
||||
Create a new ChaChaSimpleINI object.
|
||||
This is the object representing an INI file.
|
||||
|
||||
:param str filepath: INI file path
|
||||
:type index: str or None
|
||||
:param bool bForceAlwaysOutputArrays: Force API to always return an array even with one single Key/Section
|
||||
:return: The INI file
|
||||
:rtype: ChaChaSimpleINI
|
||||
:raises FileNotFoundError
|
||||
:raises PermissionError
|
||||
"""
|
||||
self.filepath = filepath
|
||||
self.bForceAlwaysOutputArrays = bForceAlwaysOutputArrays
|
||||
self.ar_sections=[]
|
||||
self.ar_tmp_sections=[]
|
||||
self.sectioncomment_tag=";"
|
||||
self.bStrict = bStrict
|
||||
|
||||
self.ar_sections.append(ChaChaSimpleINI_section_Root(bForceAlwaysOutputArrays))
|
||||
|
||||
if filepath is not None and os.path.isfile(filepath):
|
||||
with open(filepath) as file:
|
||||
lineIndex = 1
|
||||
for _line in file:
|
||||
line = _line.rstrip()
|
||||
if result := re.search(r'^\s*$',line):
|
||||
#print("find empty line, ignoring this line")
|
||||
pass
|
||||
elif result := re.search(r'^\s*;',line):
|
||||
#print("find comment, ignoring this line")
|
||||
pass
|
||||
self.ar_tmp_sections.append(ChaChaSimpleINI_section_Blank())
|
||||
elif result := re.search(r'^\s*{0}(?P<section_comment>.*)'.format(self.sectioncomment_tag),line):
|
||||
self.ar_tmp_sections.append(ChaChaSimpleINI_section_Comment(result.group('section_comment').strip()))
|
||||
elif result := re.search(r'^\s*\[(?P<section_name>.*)\]\s*$',line):
|
||||
#print("find section")
|
||||
#attach tmp Comments/Blanks sections to main Sections list
|
||||
self.ar_sections.extend(self.ar_tmp_sections)
|
||||
self.ar_tmp_sections = []
|
||||
self.addSection(result.group('section_name').strip())
|
||||
elif result := re.search(r'^\s*(?P<key_name>[^=]*)=(?P<key_value>.*)',line):
|
||||
#print("find key {0}, with value: {1}".format(result.group('key_name').strip(),result.group('key_value').strip()))
|
||||
self.ar_sections[-1].appendKey(result.group('key_name').strip(),result.group('key_value').strip())
|
||||
elif result := re.search(r'^\s*(?P<key_name>[^=]*)=(?P<key_value>.*)',line):
|
||||
#searching last Section (not comment nor Blank) in mains Sections list
|
||||
_section = None
|
||||
for section in reversed(self.ar_sections) :
|
||||
if isinstance(section, ChaChaSimpleINI_section):
|
||||
_section = section
|
||||
break
|
||||
#attach tmp Comments/Blanks Sections to Key
|
||||
for section in self.ar_tmp_sections:
|
||||
if isinstance(section, ChaChaSimpleINI_section_Blank):
|
||||
_section.appendBlankKey()
|
||||
elif isinstance(section, ChaChaSimpleINI_section_Comment):
|
||||
_section.appendCommentKey(section.value)
|
||||
|
||||
self.ar_tmp_sections = []
|
||||
|
||||
_section.appendKey(result.group('key_name').strip(),result.group('key_value').strip())
|
||||
else:
|
||||
#print("find unknown, ignoring this line")
|
||||
pass
|
||||
if bStrict:
|
||||
raise ChaChaINI_WrongFormatException("Found on line: {0}".format(lineIndex))
|
||||
|
||||
lineIndex = lineIndex + 1
|
||||
if self.ar_tmp_sections:
|
||||
self.ar_sections.extend(self.ar_tmp_sections)
|
||||
self.ar_tmp_sections = []
|
||||
|
||||
|
||||
def setFilePath(self,filepath:str):
|
||||
"""
|
||||
Change / Set the INI file path.
|
||||
example: Use this method to save your (possibly modified) INI file elsewhere.
|
||||
:param str filepath: The (new) file path
|
||||
:return: Nothing
|
||||
:rtype: None
|
||||
"""
|
||||
self.filepath = filepath
|
||||
|
||||
def formatAll(self,bBeautify:bool = False) -> str:
|
||||
"""
|
||||
Generate the full formated output.
|
||||
:param bool bBeautify: enable space arround '='
|
||||
:return: formated string
|
||||
:rtype: str
|
||||
"""
|
||||
result = ""
|
||||
for section in self.ar_sections:
|
||||
result = result + section.formatAll(bBeautify)
|
||||
if bBeautify:
|
||||
if isinstance(section,ChaChaSimpleINI_section):
|
||||
_result = section.formatAll(bBeautify)
|
||||
if _result:
|
||||
if bBeautify:
|
||||
_result = _result + "\n"
|
||||
result = result + _result
|
||||
elif isinstance(section,ChaChaSimpleINI_section_Comment):
|
||||
_result = section.formatAll()
|
||||
if _result:
|
||||
_result = _result + "\n"
|
||||
result = result + _result
|
||||
elif isinstance(section,ChaChaSimpleINI_section_Blank):
|
||||
result = result + "\n"
|
||||
|
||||
return result
|
||||
|
||||
def delSection(self,name:str,index:int = None) -> None:
|
||||
"""
|
||||
Delete an existing Section.
|
||||
If index is set, only this one will be deleted (if found).
|
||||
An exception will be raised if the section isn't found.
|
||||
|
||||
:param str name: The Section name
|
||||
:param index: The Section instance index (in case of multiple section with same name)
|
||||
:type index: int or None
|
||||
:return: Number of deleted sections
|
||||
:rtype: int
|
||||
:raises ChaChaINI_SectionNotFoundException
|
||||
"""
|
||||
sections = self.getSection(name)
|
||||
if isinstance(sections,ChaChaSimpleINI_section):
|
||||
_sections=[]
|
||||
_sections.append(sections)
|
||||
sections=_sections
|
||||
i = 0
|
||||
ndeleted = 0
|
||||
for section in sections:
|
||||
if isinstance(section,ChaChaSimpleINI_section):
|
||||
indexok = True
|
||||
if index is not None:
|
||||
indexok = False
|
||||
if index == i:
|
||||
indexok = True
|
||||
if indexok:
|
||||
self.ar_sections.remove(section)
|
||||
ndeleted = ndeleted + 1
|
||||
i=i+1
|
||||
return ndeleted
|
||||
|
||||
def addSection(self,name:str) -> None:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
section = ChaChaSimpleINI_section(name)
|
||||
self.ar_sections.append(section)
|
||||
return section
|
||||
|
||||
|
||||
def addCommentSection(self,value:str) -> None:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
section = ChaChaSimpleINI_section_Comment(value)
|
||||
self.ar_sections.append(section)
|
||||
return section
|
||||
|
||||
def addBlankSection(self) -> None:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
section = ChaChaSimpleINI_section_Blank()
|
||||
self.ar_sections.append(section)
|
||||
return section
|
||||
|
||||
def writeFile(self,bBeautify:bool = False) -> None:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
with open(self.filepath,'w') as file:
|
||||
file.write(self.formatAll(bBeautify))
|
||||
|
||||
def getAllSectionNames(self) -> list[str]:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
result=[]
|
||||
for section in self.ar_sections:
|
||||
result.append(section.name)
|
||||
if isinstance(section,ChaChaSimpleINI_section):
|
||||
result.append(section.name)
|
||||
return result
|
||||
|
||||
def getSection(self,name:str) -> Union[ChaChaSimpleINI_section,list[ChaChaSimpleINI_section]]:
|
||||
result = None
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
|
||||
if self.bForceAlwaysOutputArrays:
|
||||
result = []
|
||||
else:
|
||||
result = None
|
||||
for section in self.ar_sections:
|
||||
if name == section.name:
|
||||
if result is None:
|
||||
result = section
|
||||
elif isinstance(result,ChaChaSimpleINI_section):
|
||||
result = [result,section]
|
||||
else:
|
||||
result.append(section)
|
||||
if isinstance(section,ChaChaSimpleINI_section):
|
||||
if name == section.name:
|
||||
if self.bForceAlwaysOutputArrays:
|
||||
result.append(section)
|
||||
else:
|
||||
if result is None:
|
||||
result = section
|
||||
elif isinstance(result,ChaChaSimpleINI_section):
|
||||
result = [result,section]
|
||||
else:
|
||||
result.append(section)
|
||||
if result is None:
|
||||
raise ChaChaINI_SectionNotFoundException()
|
||||
return result
|
||||
|
||||
def getAllKeyNames(self,sectionName:str)->list[str]:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
sections = self.getSection(sectionName)
|
||||
if isinstance(sections,ChaChaSimpleINI_section):
|
||||
return sections.getAllKeyNames()
|
||||
else:
|
||||
result = []
|
||||
for section in sections:
|
||||
result.extend(section.getAllKeyNames())
|
||||
if isinstance(section,ChaChaSimpleINI_section):
|
||||
result.extend(section.getAllKeyNames())
|
||||
return result
|
||||
|
||||
def delKey(self,sectionName:str,keyName:str,index:int = None,value:str = None) -> None:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
sections = self.getSection(sectionName)
|
||||
if isinstance(sections,ChaChaSimpleINI_section):
|
||||
_sections=[]
|
||||
_sections.append(sections)
|
||||
sections = _sections
|
||||
|
||||
ndeleted = 0
|
||||
for section in sections:
|
||||
if isinstance(section,ChaChaSimpleINI_section):
|
||||
try:
|
||||
ndeleted = ndeleted + section.delKey(keyName,index,value)
|
||||
except ChaChaINI_KeyNotFoundException:
|
||||
pass
|
||||
|
||||
if ndeleted == 0:
|
||||
raise ChaChaINI_KeyNotFoundException()
|
||||
|
||||
return ndeleted
|
||||
|
||||
def getKey(self,sectionName:str,keyName:str)->Union[str,list[str]]:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
sections = self.getSection(sectionName)
|
||||
if isinstance(sections,ChaChaSimpleINI_section):
|
||||
return sections.getKey(keyName)
|
||||
else:
|
||||
result = []
|
||||
for section in sections:
|
||||
try:
|
||||
keys = section.getKey(keyName)
|
||||
if isinstance(keys,ChaChaSimpleINI_key):
|
||||
#print("d {0}".format(keys))
|
||||
result.append(keys)
|
||||
else: #array
|
||||
#print("e {0}".format(keys))
|
||||
result.extend(keys)
|
||||
except ChaChaINI_KeyNotFoundException:
|
||||
pass
|
||||
if isinstance(section,ChaChaSimpleINI_section):
|
||||
try:
|
||||
keys = section.getKey(keyName)
|
||||
if isinstance(keys,ChaChaSimpleINI_key):
|
||||
#print("d {0}".format(keys))
|
||||
result.append(keys)
|
||||
else: #array
|
||||
#print("e {0}".format(keys))
|
||||
result.extend(keys)
|
||||
except ChaChaINI_KeyNotFoundException:
|
||||
pass
|
||||
if not result:
|
||||
raise ChaChaINI_KeyNotFoundException()
|
||||
|
||||
if len(result) == 1:
|
||||
return result[0]
|
||||
if self.bForceAlwaysOutputArrays:
|
||||
return result
|
||||
else:
|
||||
return result[0]
|
||||
else:
|
||||
return result
|
||||
|
||||
def getKeyValue(self,sectionName:str,keyName:str)->Union[str,list[str]]:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
sections = self.getSection(sectionName)
|
||||
if isinstance(sections,ChaChaSimpleINI_section):
|
||||
#print("c")
|
||||
@@ -206,25 +679,37 @@ class ChaChaSimpleINI:
|
||||
#print("d")
|
||||
result = []
|
||||
for section in sections:
|
||||
try:
|
||||
keys = section.getKeyValue(keyName)
|
||||
if isinstance(keys,str):
|
||||
#print("d {0}".format(keys))
|
||||
result.append(keys)
|
||||
else: #array
|
||||
#print("e {0}".format(keys))
|
||||
result.extend(keys)
|
||||
except ChaChaINI_KeyNotFoundException:
|
||||
pass
|
||||
if isinstance(section,ChaChaSimpleINI_section):
|
||||
try:
|
||||
keys = section.getKeyValue(keyName)
|
||||
if isinstance(keys,str):
|
||||
#print("d {0}".format(keys))
|
||||
result.append(keys)
|
||||
else: #array
|
||||
#print("e {0}".format(keys))
|
||||
result.extend(keys)
|
||||
except ChaChaINI_KeyNotFoundException:
|
||||
pass
|
||||
if not result:
|
||||
raise ChaChaINI_KeyNotFoundException()
|
||||
|
||||
if len(result) == 1:
|
||||
return result[0]
|
||||
if self.bForceAlwaysOutputArrays:
|
||||
return result
|
||||
else:
|
||||
return result[0]
|
||||
else:
|
||||
return result
|
||||
|
||||
def setAddKeyValue(self,sectionName:str,keyName:str,keyValue:str,bForceAddKey:bool = False,bForceAddSection:bool = False)->Union[str,list[str]]:
|
||||
"""
|
||||
|
||||
:param str name:
|
||||
:type index:
|
||||
:return:
|
||||
:rtype:
|
||||
:raises
|
||||
"""
|
||||
if bForceAddSection:
|
||||
sections = self.addSection(sectionName)
|
||||
else:
|
||||
|
||||
@@ -4,24 +4,33 @@ from pathlib import Path
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
import io
|
||||
sys.path.append('../')
|
||||
|
||||
from ChaChaSimpleINI import *
|
||||
|
||||
|
||||
|
||||
|
||||
class Test_ChaChaSimpleINI_base(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
[f.unlink() for f in Path("tmp").glob("*")]
|
||||
print("======================")
|
||||
|
||||
|
||||
def test_simpleread_value(self):
|
||||
testini = ChaChaSimpleINI("testfiles/test_simpleread.ini")
|
||||
self.assertEqual(testini.getKeyValue("testsection", "key1"),"test")
|
||||
self.assertEqual(testini.getKeyValue("testsection", "key2"), "2")
|
||||
self.assertEqual(testini.getKeyValue("testsection", "key3"), "43")
|
||||
self.assertEqual(testini.getKeyValue("testsection", "key4"), "0.54")
|
||||
|
||||
def test_simpleread_value__bForceAlwaysOutputArrays(self):
|
||||
testini = ChaChaSimpleINI("testfiles/test_simpleread.ini",True)
|
||||
self.assertEqual(testini.getKeyValue("testsection", "key1"),["test"])
|
||||
self.assertEqual(testini.getKeyValue("testsection", "key2"), ["2"])
|
||||
self.assertEqual(testini.getKeyValue("testsection", "key3"), ["43"])
|
||||
self.assertEqual(testini.getKeyValue("testsection", "key4"), ["0.54"])
|
||||
|
||||
def test_complexread1_value(self):
|
||||
testini = ChaChaSimpleINI("testfiles/test_complexread1.ini")
|
||||
@@ -36,23 +45,189 @@ class Test_ChaChaSimpleINI_base(unittest.TestCase):
|
||||
|
||||
|
||||
self.assertEqual(testini.getKeyValue("test section 4", "test key two"),"test value two")
|
||||
|
||||
def test_simpleread_section_comment(self):
|
||||
testini = ChaChaSimpleINI("testfiles/test_comment.ini")
|
||||
self.assertEqual(testini.getKeyValue("testsection1", "key1"),"test1")
|
||||
testini.setFilePath("tmp/out3.ini")
|
||||
testini.writeFile(False)
|
||||
testinitmp = ChaChaSimpleINI("tmp/out3.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection1", "key1"), "test1")
|
||||
self.assertListEqual(list(io.open("testfiles/test_comment.ini")),list(io.open("tmp/out3.ini")))
|
||||
|
||||
def test_complexread1_value__bForceAlwaysOutputArrays(self):
|
||||
testini = ChaChaSimpleINI("testfiles/test_complexread1.ini",True)
|
||||
self.assertEqual(testini.getKeyValue("testsection1", "key1"),["test1"])
|
||||
self.assertEqual(testini.getKeyValue("testsection1", "key2"),["test2"])
|
||||
self.assertEqual(testini.getKeyValue("testsection1", "key3"),["test3"])
|
||||
self.assertEqual(testini.getKeyValue("testsection1", "key4"),["test4"])
|
||||
|
||||
self.assertEqual(testini.getKeyValue("testsection2", "key1"),["test1"])
|
||||
self.assertEqual(testini.getKeyValue("testsection2", "key2"),["test2","test3"])
|
||||
self.assertEqual(testini.getKeyValue("testsection2", "keya"),["0"])
|
||||
|
||||
|
||||
self.assertEqual(testini.getKeyValue("test section 4", "test key two"),["test value two"])
|
||||
|
||||
def test_complexreadwrite_value(self):
|
||||
testini = ChaChaSimpleINI("testfiles/test_complexreadwrite.ini")
|
||||
self.assertEqual(testini.getKeyValue("testsection", "key"), ["test1","test2","test3"])
|
||||
testini.sefFilePath("tmp/out.ini")
|
||||
testini.setFilePath("tmp/out.ini")
|
||||
testini.writeFile(False)
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection", "key"), ["test1","test2","test3"])
|
||||
|
||||
testini.setAddKeyValue("testsection", "key", "test4", True)
|
||||
testini.sefFilePath("tmp/out2.ini")
|
||||
testini.setFilePath("tmp/out2.ini")
|
||||
testini.writeFile(False)
|
||||
testinitmp = ChaChaSimpleINI("tmp/out2.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection", "key"), ["test1","test2","test3","test4"])
|
||||
|
||||
testini.setAddKeyValue("testsection", "key", "test4", True,True)
|
||||
testini.sefFilePath("tmp/out3.ini")
|
||||
testini.setFilePath("tmp/out3.ini")
|
||||
testini.writeFile(True)
|
||||
testinitmp = ChaChaSimpleINI("tmp/out3.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection", "key"), ["test1","test2","test3","test4","test4"])
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection", "key"), ["test1","test2","test3","test4","test4"])
|
||||
|
||||
def test_deletekey(self):
|
||||
#create copy of the file
|
||||
testini = ChaChaSimpleINI("testfiles/test_delete.ini")
|
||||
testini.setFilePath("tmp/out.ini")
|
||||
testini.writeFile(False)
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
section = testinitmp.getSection("testsection2")
|
||||
section.delKey("key1")
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
with self.assertRaises(ChaChaINI_KeyNotFoundException):
|
||||
testinitmp.getKeyValue("testsection2", "key1")
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
section = testinitmp.getSection("testsection2")
|
||||
section.delKey("key2",2)
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection2", "key2"), ["test2","test3"])
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
section = testinitmp.getSection("testsection2")
|
||||
section.delKey("key2",None,"test3")
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection2", "key2"), "test2")
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
section = testinitmp.getSection("testsection1")
|
||||
with self.assertRaises(ChaChaINI_KeyNotFoundException):
|
||||
section.delKey("key2",1,"test2")
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
section = testinitmp.getSection("testsection1")
|
||||
section.delKey("key2",1,"test3")
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection1", "key2"), "test2")
|
||||
|
||||
def test_deletesection(self):
|
||||
#create copy of the file
|
||||
testini = ChaChaSimpleINI("testfiles/test_delete.ini")
|
||||
testini.setFilePath("tmp/out.ini")
|
||||
testini.writeFile(False)
|
||||
|
||||
#remove a section
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
testinitmp.delSection("testsection1")
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
with self.assertRaises(ChaChaINI_SectionNotFoundException):
|
||||
testinitmp.getSection("testsection1")
|
||||
|
||||
#remove a section
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
testinitmp.delSection("testsection2",1)
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
testinitmp.getSection("testsection2")
|
||||
|
||||
#remove a section
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
testinitmp.delSection("testsection2",0)
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
with self.assertRaises(ChaChaINI_SectionNotFoundException):
|
||||
testinitmp.getSection("testsection2")
|
||||
|
||||
#remove a section
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
with self.assertRaises(ChaChaINI_SectionNotFoundException):
|
||||
testinitmp.delSection("testsection2",0)
|
||||
|
||||
def test_deletekey_fromfile(self):
|
||||
|
||||
#create copy of the file
|
||||
testini = ChaChaSimpleINI("testfiles/test_delete.ini")
|
||||
testini.setFilePath("tmp/out.ini")
|
||||
testini.writeFile(False)
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
testinitmp.delKey("testsection2","key1")
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
with self.assertRaises(ChaChaINI_KeyNotFoundException):
|
||||
testinitmp.getKeyValue("testsection2", "key1")
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
testinitmp.delKey("testsection2","key2",2)
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection2", "key2"), ["test2","test3"])
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
testinitmp.delKey("testsection2","key2",None,"test3")
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection2", "key2"), "test2")
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
with self.assertRaises(ChaChaINI_KeyNotFoundException):
|
||||
testinitmp.delKey("testsection1","key2",1,"test2")
|
||||
|
||||
#create copy of the file
|
||||
testini = ChaChaSimpleINI("testfiles/test_delete.ini")
|
||||
testini.setFilePath("tmp/out.ini")
|
||||
testini.writeFile(False)
|
||||
|
||||
#remove an item
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
testinitmp.delKey("testsection1","key2",1,"test3")
|
||||
testinitmp.writeFile(True)
|
||||
#verify
|
||||
testinitmp = ChaChaSimpleINI("tmp/out.ini")
|
||||
self.assertEqual(testinitmp.getKeyValue("testsection1", "key2"), "test2")
|
||||
|
||||
|
||||
def test_strict_mode(self):
|
||||
with self.assertRaises(ChaChaINI_WrongFormatException):
|
||||
testini = ChaChaSimpleINI("testfiles/test_strict.ini",False,True)
|
||||
|
||||
testini = ChaChaSimpleINI("testfiles/test_strict.ini",False,False)
|
||||
Reference in New Issue
Block a user