complete doc
This commit is contained in:
@@ -23,9 +23,183 @@ From master git repository:
|
||||
|
||||
Add this line on the top of your python script:
|
||||
```py
|
||||
from pysimpleini import pysimpleini
|
||||
from pysimpleini import PySimpleINI
|
||||
```
|
||||
|
||||
## Basic API
|
||||
|
||||
TO DO
|
||||
### Sample INI File:
|
||||
|
||||
```console
|
||||
[testsection]
|
||||
key1=test1
|
||||
key2=test2
|
||||
key3=test3
|
||||
key3=test31
|
||||
|
||||
[testsection2]
|
||||
key10=test10
|
||||
```
|
||||
|
||||
### Load the INI File:
|
||||
|
||||
```py
|
||||
myini:PySimpleINI = PySimpleINI("myinifile.ini")
|
||||
```
|
||||
|
||||
### Access simple key values:
|
||||
|
||||
```py
|
||||
print(myini.getkeyvalue("testsection", "key1"))
|
||||
```
|
||||
```console
|
||||
test1
|
||||
```
|
||||
|
||||
```py
|
||||
print(myini.getkeyvalue("testsection", "key2"))
|
||||
```
|
||||
```console
|
||||
test2
|
||||
```
|
||||
|
||||
```py
|
||||
print(myini.getkeyvalue("testsection", "key3"))
|
||||
```
|
||||
```console
|
||||
['test3','test31']
|
||||
```
|
||||
|
||||
```py
|
||||
print(myini.getkeyvalue("testsection", "key3"))
|
||||
```
|
||||
```console
|
||||
['test3','test31']
|
||||
```
|
||||
|
||||
### Access key values with specified index:
|
||||
|
||||
```py
|
||||
print(myini.getkeyvalue_ex("testsection", "key3",0))
|
||||
```
|
||||
```console
|
||||
test3
|
||||
```
|
||||
|
||||
```py
|
||||
print(myini.getkeyvalue_ex("testsection", "key3",1))
|
||||
```
|
||||
```console
|
||||
test31
|
||||
```
|
||||
|
||||
### list keys name:
|
||||
|
||||
```py
|
||||
print(myini.getallkeynames("testsection"))
|
||||
```
|
||||
```console
|
||||
['key1', 'key2', 'key3', 'key3']
|
||||
```
|
||||
|
||||
### list sections name:
|
||||
|
||||
```py
|
||||
print(myini.getallsectionnames())
|
||||
```
|
||||
```console
|
||||
['testsection', 'testsection2']
|
||||
```
|
||||
|
||||
### add a new key:
|
||||
|
||||
```py
|
||||
myini.setaddkeyvalue("testsection2","key11","test11")
|
||||
print(myini.format())
|
||||
```
|
||||
```console
|
||||
[testsection]
|
||||
key1=test1
|
||||
key2=test2
|
||||
key3=test3
|
||||
key3=test31
|
||||
[testsection2]
|
||||
key10=test10
|
||||
key11=test11
|
||||
```
|
||||
|
||||
### update a key value:
|
||||
|
||||
```py
|
||||
myini.setaddkeyvalue("testsection2","key11","test13")
|
||||
print(myini.format())
|
||||
```
|
||||
```console
|
||||
[testsection]
|
||||
key1=test1
|
||||
key2=test2
|
||||
key3=test3
|
||||
key3=test31
|
||||
[testsection2]
|
||||
key10=test10
|
||||
key11=test13
|
||||
```
|
||||
|
||||
### create a new key with same name:
|
||||
|
||||
```py
|
||||
myini.setaddkeyvalue("testsection2","key11","test14",True)
|
||||
print(myini.format())
|
||||
```
|
||||
```console
|
||||
[testsection]
|
||||
key1=test1
|
||||
key2=test2
|
||||
key3=test3
|
||||
key3=test31
|
||||
[testsection2]
|
||||
key10=test10
|
||||
key11=test13
|
||||
key11=test14
|
||||
```
|
||||
|
||||
### create a new empty section
|
||||
|
||||
```py
|
||||
myini.addsection("testsection3")
|
||||
print(myini.format())
|
||||
```
|
||||
```console
|
||||
[testsection]
|
||||
key1=test1
|
||||
key2=test2
|
||||
key3=test3
|
||||
key3=test31
|
||||
[testsection2]
|
||||
key10=test10
|
||||
key11=test13
|
||||
key11=test14
|
||||
[testsection3]
|
||||
```
|
||||
|
||||
### save your file
|
||||
```py
|
||||
myini.writefile()
|
||||
```
|
||||
|
||||
### save to a new file
|
||||
```py
|
||||
myini.filepath = "somedir/somefile.ini"
|
||||
myini.writefile()
|
||||
```
|
||||
|
||||
__Read the API documentation and the unit test for more informations __
|
||||
|
||||
## limitations
|
||||
|
||||
There is some known limitations.
|
||||
|
||||
1. File is only written when writefile() is called.
|
||||
|
||||
2. Support for more than one section with the same name is incomplete using setaddkeyvalue() / getkeyvalue_ex() / getkey_ex() / delkey_ex() because the index argument is only for keys.
|
||||
If more precise section selection is needed, please use getsection() to get the correct section object and then use the underlying methods.
|
||||
|
||||
@@ -17,6 +17,9 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from re import search as RE_search
|
||||
|
||||
from .walker import Walker
|
||||
from .exceptions import SectionNotFoundError
|
||||
|
||||
from .sections import (
|
||||
SectionBase,
|
||||
Section,
|
||||
@@ -52,6 +55,104 @@ class Document:
|
||||
"""reset sections list"""
|
||||
self._sections = []
|
||||
|
||||
def addsection(self, name: str) -> Section:
|
||||
"""Create and Add a new Section.
|
||||
|
||||
Args:
|
||||
name: The new section name
|
||||
Returns:
|
||||
The new section
|
||||
"""
|
||||
section = Section(name, -1)
|
||||
self.sections.append(section)
|
||||
return section
|
||||
|
||||
def addcommentsection(self, value: str) -> SectionComment:
|
||||
"""Create and Add a new Comment Section.
|
||||
|
||||
Args:
|
||||
value: Comment value
|
||||
Returns:
|
||||
The new section
|
||||
"""
|
||||
section = SectionComment(-1)
|
||||
section.append_commentkey(self.sectioncomment_tags[0], value, -1)
|
||||
self.sections.append(section)
|
||||
return section
|
||||
|
||||
def addblanksection(self) -> SectionBlanck:
|
||||
"""Create and Add a new Blank Section (newline).
|
||||
|
||||
Returns:
|
||||
The new section
|
||||
"""
|
||||
section = SectionBlanck(-1)
|
||||
section.append_blanckkey(-1)
|
||||
self.sections.append(section)
|
||||
return section
|
||||
|
||||
def delsection(self, name: str, index: Optional[int] = None) -> int:
|
||||
"""Delete an existing Section.
|
||||
|
||||
- If index is set, this filter will be applied.
|
||||
|
||||
///warning
|
||||
An exception will be raised if the Section isn't found.
|
||||
///
|
||||
|
||||
Args:
|
||||
name: The Section name
|
||||
index: The Section instance index (in case of multiple section with same name)
|
||||
Returns:
|
||||
Number of deleted sections
|
||||
"""
|
||||
|
||||
walker = Walker[SectionBase](targetname=name, targetindex=index, targettypes=Section)
|
||||
walker.walk(self.sections, self.sections.remove)
|
||||
ndeleted: int = walker.num_matched
|
||||
|
||||
if ndeleted == 0:
|
||||
raise SectionNotFoundError()
|
||||
|
||||
return ndeleted
|
||||
|
||||
def getallsectionnames(self) -> list[str]:
|
||||
"""Retrieve a list of sections names.
|
||||
|
||||
Returns:
|
||||
List of section names.
|
||||
"""
|
||||
result = []
|
||||
|
||||
walker = Walker[SectionBase](targettypes=Section)
|
||||
walker.walk(self.sections, lambda x: result.append(x.getname()))
|
||||
|
||||
return result
|
||||
|
||||
def getsection(self, name: str, index: Optional[int] = None) -> list[Section]:
|
||||
"""Get one or more sections objects.
|
||||
|
||||
///Note
|
||||
An exception will be raised if the Section isn't found.
|
||||
///
|
||||
|
||||
Args:
|
||||
name: Name of the section to retrieve.
|
||||
index: The Section instance index (in case of multiple section with same name)
|
||||
Returns:
|
||||
The section object or a list of section object
|
||||
"""
|
||||
|
||||
result: List[Section] = []
|
||||
|
||||
walker = Walker[SectionBase](targetname=name, targetindex=index, targettypes=Section)
|
||||
walker.walk(self.sections, result.append)
|
||||
|
||||
if len(result) == 0:
|
||||
raise SectionNotFoundError()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class DocumentParser(Document):
|
||||
"""Document Parser class"""
|
||||
|
||||
@@ -22,7 +22,7 @@ from pathlib import Path
|
||||
|
||||
from .document import DocumentParser, DocumentFormater
|
||||
from .walker import Walker
|
||||
from .sections import Section, SectionComment, SectionBlanck, SectionBase
|
||||
from .sections import Section, SectionBase
|
||||
from .keys import Key
|
||||
from .exceptions import SectionNotFoundError, KeyNotFoundError
|
||||
|
||||
@@ -90,67 +90,6 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
self.parse(file.read())
|
||||
return self
|
||||
|
||||
def delsection(self, name: str, index: Optional[int] = None) -> int:
|
||||
"""Delete an existing Section.
|
||||
|
||||
- If index is set, this filter will be applied.
|
||||
|
||||
///warning
|
||||
An exception will be raised if the Section isn't found.
|
||||
///
|
||||
|
||||
Args:
|
||||
name: The Section name
|
||||
index: The Section instance index (in case of multiple section with same name)
|
||||
Returns:
|
||||
Number of deleted sections
|
||||
"""
|
||||
|
||||
walker = Walker[SectionBase](targetname=name, targetindex=index, targettypes=Section)
|
||||
walker.walk(self.sections, self.sections.remove)
|
||||
ndeleted: int = walker.num_matched
|
||||
|
||||
if ndeleted == 0:
|
||||
raise SectionNotFoundError()
|
||||
|
||||
return ndeleted
|
||||
|
||||
def addsection(self, name: str) -> Section:
|
||||
"""Create and Add a new Section.
|
||||
|
||||
Args:
|
||||
name: The new sectio nname
|
||||
Returns:
|
||||
The new section
|
||||
"""
|
||||
section = Section(name, -1)
|
||||
self.sections.append(section)
|
||||
return section
|
||||
|
||||
def addcommentsection(self, value: str) -> SectionComment:
|
||||
"""Create and Add a new Comment Section.
|
||||
|
||||
Args:
|
||||
value: Comment value
|
||||
Returns:
|
||||
The new section
|
||||
"""
|
||||
section = SectionComment(-1)
|
||||
section.append_commentkey(self.sectioncomment_tags[0], value, -1)
|
||||
self.sections.append(section)
|
||||
return section
|
||||
|
||||
def addblanksection(self) -> SectionBlanck:
|
||||
"""Create and Add a new Blank Section (newline).
|
||||
|
||||
Returns:
|
||||
The new section
|
||||
"""
|
||||
section = SectionBlanck(-1)
|
||||
section.append_blanckkey(-1)
|
||||
self.sections.append(section)
|
||||
return section
|
||||
|
||||
def writefile(self, bBeautify: bool = False, bWipeComments: bool = False) -> None:
|
||||
"""Actually write the INI object to the file.
|
||||
|
||||
@@ -162,44 +101,6 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
with open(self._filepath, "w", encoding="utf-8") as file:
|
||||
file.write(self.format(bBeautify, bWipeComments))
|
||||
|
||||
def getallsectionnames(self) -> list[str]:
|
||||
"""Retrieve a list of sections names.
|
||||
|
||||
Returns:
|
||||
List of section names.
|
||||
"""
|
||||
result = []
|
||||
|
||||
walker = Walker[SectionBase](targettypes=Section)
|
||||
walker.walk(self.sections, lambda x: result.append(x.getname()))
|
||||
|
||||
return result
|
||||
|
||||
def getsection(self, name: str) -> Section | list[Section]:
|
||||
"""Get one or more sections objects.
|
||||
|
||||
///Note
|
||||
An exception will be raised if the Section isn't found.
|
||||
///
|
||||
|
||||
Args:
|
||||
name: Name of the section to retrieve.
|
||||
Returns:
|
||||
The section object or a list of section object
|
||||
"""
|
||||
|
||||
result: List[Section] = []
|
||||
|
||||
walker = Walker[SectionBase](targetname=name, targettypes=Section)
|
||||
walker.walk(self.sections, result.append)
|
||||
|
||||
if len(result) == 0:
|
||||
raise SectionNotFoundError()
|
||||
|
||||
if not self._bForceAlwaysOutputArrays and (len(result) == 1):
|
||||
return result[0]
|
||||
return result
|
||||
|
||||
def getallkeynames(self, sectionName: str) -> list[str]:
|
||||
"""Get a list of Keys in a defined Section.
|
||||
|
||||
@@ -207,6 +108,10 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
An exception will be raised if the Key or Section isn't found.
|
||||
///
|
||||
|
||||
///Note
|
||||
All section with given name will be considered.
|
||||
///
|
||||
|
||||
Args:
|
||||
sectionName: The Section name
|
||||
Returns:
|
||||
@@ -222,10 +127,14 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
def delkey(self, sectionName: str, keyName: str) -> int:
|
||||
"""Delete an existing Key from Section.
|
||||
|
||||
///Note
|
||||
///warning
|
||||
An exception will be raised if the Key or Section isn't found.
|
||||
///
|
||||
|
||||
///Note
|
||||
All section with given name will be considered.
|
||||
///
|
||||
|
||||
Args:
|
||||
sectionName: The Section name
|
||||
keyName: The Key name
|
||||
@@ -242,7 +151,11 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
- Both filter can be enabled together (value appyed first)
|
||||
|
||||
///warning
|
||||
An exception will be raised if the Section isn't found.
|
||||
An exception will be raised if the Key or Section isn't found.
|
||||
///
|
||||
|
||||
///Note
|
||||
index only apply to keys index, not to section. All section with given name will be considered.
|
||||
///
|
||||
|
||||
Args:
|
||||
@@ -279,10 +192,14 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
def getkey(self, sectionName: str, keyName: str) -> Key | List[Key]:
|
||||
"""Get one or more Key from Section.
|
||||
|
||||
///Note
|
||||
///warning
|
||||
An exception will be raised if the Key or Section isn't found.
|
||||
///
|
||||
|
||||
///Note
|
||||
All section with given name will be considered.
|
||||
///
|
||||
|
||||
Args:
|
||||
sectionName: The Section name
|
||||
keyName: The Key name
|
||||
@@ -298,10 +215,19 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
- If index is set, this filter will be applied.
|
||||
- Both filter can be enabled together (value appyed first)
|
||||
|
||||
///Note
|
||||
///warning
|
||||
An exception will be raised if the Key or Section isn't found.
|
||||
///
|
||||
|
||||
///Note
|
||||
index only apply to keys index, not to section. All section with given name will be considered.
|
||||
///
|
||||
|
||||
///Note
|
||||
If this Lib is not initialized with bForceAlwaysOutputArrays set,
|
||||
this function will output a single object on single match (not a list).
|
||||
///
|
||||
|
||||
Args:
|
||||
sectionName: The Section name
|
||||
keyName: The Key name
|
||||
@@ -343,10 +269,14 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
def getkeyvalue(self, sectionName: str, keyName: str) -> str | list[str]:
|
||||
"""Get one or more Key's values from Section.
|
||||
|
||||
///Note
|
||||
///warning
|
||||
An exception will be raised if the Key or Section isn't found.
|
||||
///
|
||||
|
||||
///Note
|
||||
All section with given name will be considered.
|
||||
///
|
||||
|
||||
Args:
|
||||
sectionName: The Section name
|
||||
keyName: The Key name
|
||||
@@ -362,10 +292,14 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
- If index is set, this filter will be applied.
|
||||
- Both filter can be enabled together (value appyed first)
|
||||
|
||||
///Note
|
||||
///warning
|
||||
An exception will be raised if the Key or Section isn't found.
|
||||
///
|
||||
|
||||
///Note
|
||||
index only apply to keys index, not to section. All section with given name will be considered.
|
||||
///
|
||||
|
||||
Args:
|
||||
sectionName: The Section name
|
||||
keyName: The Key name
|
||||
@@ -385,6 +319,10 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
) -> None:
|
||||
"""Set or Add a new key with value.
|
||||
|
||||
///warning
|
||||
In case of multiple section with the same name, only the last one will be considered.
|
||||
///
|
||||
|
||||
Args:
|
||||
sectionName: The Section name
|
||||
keyName: Key's name
|
||||
@@ -392,16 +330,13 @@ class PySimpleINI(DocumentParser, DocumentFormater):
|
||||
bForceAddKey: Force to add a new Key, even if the name already exists
|
||||
bForceAddSection: Force to add a new Section, even if the name already exists
|
||||
"""
|
||||
sections: Section | List[Section]
|
||||
sections: List[Section]
|
||||
if bForceAddSection is True:
|
||||
sections = self.addsection(sectionName)
|
||||
sections = [self.addsection(sectionName)]
|
||||
else:
|
||||
try:
|
||||
sections = self.getsection(sectionName)
|
||||
except SectionNotFoundError:
|
||||
sections = self.addsection(sectionName)
|
||||
sections = [self.addsection(sectionName)]
|
||||
|
||||
if isinstance(sections, Section):
|
||||
sections.setaddkeyvalue(keyName, keyValue, bForceAddKey)
|
||||
else: # array: in this case we set value of the last section
|
||||
sections[-1].setaddkeyvalue(keyName, keyValue, bForceAddKey)
|
||||
sections[-1].setaddkeyvalue(keyName, keyValue, bForceAddKey)
|
||||
|
||||
@@ -276,3 +276,22 @@ class Test_PySimpleINI_base(unittest.TestCase):
|
||||
def test_inputForeighKeys(self):
|
||||
inputstring = "testkey1=valuetestkey1\n" "testkey2=valuetestkey2\n" "testkey3=valuetestkey3.1\n" "testkey3=valuetestkey3.2\n"
|
||||
self.Gen_test_inputstring(inputstring)
|
||||
|
||||
def test_doc_usage(self):
|
||||
inputstring = "[testsection]\n" "key1=test1\n" "key2=test2\n" "key3=test3\n" "key3=test31\n" "[testsection2]\n" "key10=test10\n"
|
||||
myini = PySimpleINI().parse(inputstring)
|
||||
print(myini.getkeyvalue("testsection", "key1"))
|
||||
print(myini.getkeyvalue("testsection", "key2"))
|
||||
print(myini.getkeyvalue("testsection", "key3"))
|
||||
print(myini.getkeyvalue_ex("testsection", "key3", 0))
|
||||
print(myini.getkeyvalue_ex("testsection", "key3", 1))
|
||||
print(myini.getallkeynames("testsection"))
|
||||
print(myini.getallsectionnames())
|
||||
myini.setaddkeyvalue("testsection2", "key11", "test11")
|
||||
print(myini.format())
|
||||
myini.setaddkeyvalue("testsection2", "key11", "test13")
|
||||
print(myini.format())
|
||||
myini.setaddkeyvalue("testsection2", "key11", "test14", True)
|
||||
print(myini.format())
|
||||
myini.addsection("testsection3")
|
||||
print(myini.format())
|
||||
|
||||
Reference in New Issue
Block a user