18
18
delimiters=('=', ':'), co
F438
mment_prefixes=('#', ';'),
19
19
inline_comment_prefixes=None, strict=True,
20
20
empty_lines_in_values=True, default_section='DEFAULT',
21
- interpolation=<unset>, converters=<unset>):
22
-
21
+ interpolation=<unset>, converters=<unset>,
22
+ allow_unnamed_section=False):
23
23
Create the parser. When `defaults` is given, it is initialized into the
24
24
dictionary or intrinsic defaults. The keys must be strings, the values
25
25
must be appropriate for %()s string interpolation.
68
68
converter gets its corresponding get*() method on the parser object and
69
69
section proxies.
70
70
71
+ When `allow_unnamed_section` is True (default: False), options
72
+ without section are accepted: the section for these is
73
+ ``configparser.UNNAMED_SECTION``.
74
+
71
75
sections()
72
76
Return all the configuration section names, sans DEFAULT.
73
77
156
160
"ConfigParser" , "RawConfigParser" ,
157
161
"Interpolation" , "BasicInterpolation" , "ExtendedInterpolation" ,
158
162
"SectionProxy" , "ConverterMapping" ,
159
- "DEFAULTSECT" , "MAX_INTERPOLATION_DEPTH" )
163
+ "DEFAULTSECT" , "MAX_INTERPOLATION_DEPTH" , "UNNAMED_SECTION" )
160
164
161
165
_default_dict = dict
162
166
DEFAULTSECT = "DEFAULT"
@@ -336,6 +340,15 @@ def __init__(self, filename, lineno, line):
336
340
self .line = line
337
341
self .args = (filename , lineno , line )
338
342
343
+ class _UnnamedSection :
344
+
345
+ def __repr__ (self ):
346
+ return "<UNNAMED_SECTION>"
347
+
348
+
349
+ UNNAMED_SECTION = _UnnamedSection ()
350
+
351
+
339
352
# Used in parser getters to indicate the default behaviour when a specific
340
353
# option is not found it to raise an exception. Created to enable `None` as
341
354
# a valid fallback value.
@@ -550,7 +563,8 @@ def __init__(self, defaults=None, dict_type=_default_dict,
550
563
comment_prefixes = ('#' , ';' ), inline_comment_prefixes = None ,
551
564
strict = True , empty_lines_in_values = True ,
552
565
default_section = DEFAULTSECT ,
553
- interpolation = _UNSET , converters = _UNSET ):
566
+ interpolation = _UNSET , converters = _UNSET ,
567
+ allow_unnamed_section = False ,):
554
568
555
569
self ._dict = dict_type
556
570
self ._sections = self ._dict ()
@@ -589,6 +603,7 @@ def __init__(self, defaults=None, dict_type=_default_dict,
589
603
self ._converters .update (converters )
590
604
if defaults :
591
605
self ._read_defaults (defaults )
606
+ self ._allow_unnamed_section = allow_unnamed_section
592
607
593
608
def defaults (self ):
594
609
return self ._defaults
@@ -862,13 +877,19 @@ def write(self, fp, space_around_delimiters=True):
862
877
if self ._defaults :
863
878
self ._write_section (fp , self .default_section ,
864
879
self ._defaults .items (), d )
880
+ if UNNAMED_SECTION in self ._sections :
881
+ self ._write_section (fp , UNNAMED_SECTION , self ._sections [UNNAMED_SECTION ].items (), d , unnamed = True )
882
+
865
883
for section in self ._sections :
884
+ if section is UNNAMED_SECTION :
885
+ continue
866
886
self ._write_section (fp , section ,
867
887
self ._sections [section ].items (), d )
868
888
869
- def _write_section (self , fp , section_name , section_items , delimiter ):
870
- """Write a single section to the specified `fp`."""
871
- fp .write ("[{}]\n " .format (section_name ))
889
+ def _write_section (self , fp , section_name , section_items , delimiter , unnamed = False ):
890
+ """Write a single section to the specified `fp'."""
891
+ if not unnamed :
892
+ fp .write ("[{}]\n " .format (section_name ))
872
893
for key , value in section_items :
873
894
value = self ._interpolation .before_write (self , section_name , key ,
874
895
value )
@@ -961,6 +982,7 @@ def _read(self, fp, fpname):
961
982
lineno = 0
962
983
indent_level = 0
963
984
e = None # None, or an exception
985
+
964
986
try :
965
987
for lineno , line in enumerate (fp , start = 1 ):
966
988
comment_start = sys .maxsize
@@ -1007,6 +1029,13 @@ def _read(self, fp, fpname):
1007
1029
cursect [optname ].append (value )
1008
1030
# a section header or option header?
1009
1031
else :
1032
+ if self ._allow_unnamed_section and cursect is None :
1033
+ sectname = UNNAMED_SECTION
1034
+ cursect = self ._dict ()
1035
+ self ._sections [sectname ] = cursect
1036
+ self ._proxies [sectname ] = SectionProxy (self , sectname )
1037
+ elements_added .add (sectname )
1038
+
1010
1039
indent_level = cur_indent_level
1011
1040
# is it a section header?
1012
1041
mo = self .SECTCRE .match (value )
@@ -1027,36 +1056,61 @@ def _read(self, fp, fpname):
1027
1056
elements_added .add (sectname )
1028
1057
# So sections can't start with a continuation line
1029
1058
optname = None
1030
- # no section header in the file ?
1059
+ # no section header?
1031
1060
elif cursect is None :
1032
1061
raise MissingSectionHeaderError (fpname , lineno , line )
1033
- # an option line?
1062
+ # an option line?
1034
1063
else :
1035
- mo = self ._optcre .match (value )
1064
+ indent_level = cur_indent_level
1065
+ # is it a section header?
1066
+ mo = self .SECTCRE .match (value )
1036
1067
if mo :
1037
- optname , vi , optval = mo .group ('option' , 'vi' , 'value' )
1038
- if not optname :
1039
- e = self ._handle_error (e , fpname , lineno , line )
1040
- optname = self .optionxform (optname .rstrip ())
1041
- if (self ._strict and
1042
- (sectname , optname ) in elements_added ):
1043
- raise DuplicateOptionError (sectname , optname ,
1044
- fpname , lineno )
1045
- elements_added .add ((sectname , optname ))
1046
- # This check is fine because the OPTCRE cannot
1047
- # match if it would set optval to None
1048
- if optval is not None :
1049
- optval = optval .strip ()
1050
- cursect [optname ] = [optval ]
1068
+ sectname = mo .group ('header' )
1069
+ if sectname in self ._sections :
1070
+ if self ._strict and sectname in elements_added :
1071
+ raise DuplicateSectionError (sectname , fpname ,
1072
+ lineno )
<
10000
tr class="diff-line-row">
1073
+ cursect = self ._sections [sectname ]
1074
+ elements_added .add (sectname )
1075
+ elif sectname == self .default_section :
1076
+ cursect = self ._defaults
1051
1077
else :
1052
- # valueless option handling
1053
- cursect [optname ] = None
1078
+ cursect = self ._dict ()
1079
+ self ._sections [sectname ] = cursect
1080
+ self ._proxies [sectname ] = SectionProxy (self , sectname )
1081
+ elements_added .add (sectname )
1082
+ # So sections can't start with a continuation line
1083
+ optname = None
1084
+ # no section header in the file?
1085
+ elif cursect is None :
1086
+ raise MissingSectionHeaderError (fpname , lineno , line )
1087
+ # an option line?
1054
1088
else :
1055
- # a non-fatal parsing error occurred. set up the
1056
- # exception but keep going. the exception will be
1057
- # raised at the end of the file and will contain a
1058
- # list of all bogus lines
1059
- e = self ._handle_error (e , fpname , lineno , line )
1089
+ mo = self ._optcre .match (value )
1090
+ if mo :
1091
+ optname , vi , optval = mo .group ('option' , 'vi' , 'value' )
1092
+ if not optname :
1093
+ e = self ._handle_error (e , fpname , lineno , line )
1094
+ optname = self .optionxform (optname .rstrip ())
1095
+ if (self ._strict and
1096
+ (sectname , optname ) in elements_added ):
1097
+ raise DuplicateOptionError (sectname , optname ,
1098
+ fpname , lineno )
1099
+ elements_added .add ((sectname , optname ))
1100
+ # This check is fine because the OPTCRE cannot
1101
+ # match if it would set optval to None
1102
+ if optval is not None :
1103
+ optval = optval .strip ()
1104
+ cursect [optname ] = [optval ]
1105
+ else :
1106
+ # valueless option handling
1107
+ cursect [optname ] = None
1108
+ else :
1109
+ # a non-fatal parsing error occurred. set up the
1110
+ # exception but keep going. the exception will be
1111
+ # raised at the end of the file and will contain a
1112
+ # list of all bogus lines
1113
+ e = self ._handle_error (e , fpname , lineno , line )
1060
1114
finally :
1061
1115
self ._join_multiline_values ()
1062
1116
# if any parsing errors occurred, raise an exception
0 commit comments