Skip to content

Commit

Permalink
Add missing unit tests for logging in response to issue #34.
Browse files Browse the repository at this point in the history
Also fixed the inadvert cloning of data structure thus getting clobbered by later and deeper functions.  Use `copy.deepcopy` to clone ParserElements

- Looks like 2.4.9 PyParsing debug element went away.... :-/  What fun it is going to be
  • Loading branch information
egberts committed Jun 1, 2022
1 parent bb97bb3 commit 1863739
Show file tree
Hide file tree
Showing 6 changed files with 1,303 additions and 681 deletions.
205 changes: 134 additions & 71 deletions bind9_parser/isc_clause_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,49 @@
Description: Provides logging channels-related grammar in
PyParsing engine for ISC-configuration style
logging {
category <string> { <string>; ... }; // may occur multiple times
channel <string> {
buffered <boolean>;
file <quoted_string> [ versions ( unlimited | <integer> ) ]
[ size <size> ] [ suffix ( increment | timestamp ) ];
null;
print-category <boolean>;
print-severity <boolean>;
print-time ( iso8601 | iso8601-utc | local | <boolean> );
severity <log_severity>;
stderr;
syslog [ <syslog_facility> ];
}; // may occur multiple times
};
"""
import copy

from pyparsing import Word, Group, Optional, Keyword, Literal, \
srange, OneOrMore, ZeroOrMore
srange, OneOrMore, ZeroOrMore, Char, ungroup, Combine
from bind9_parser.isc_utils import semicolon, number_type, \
isc_boolean, lbrack, rbrack, \
name_type, dequoted_path_name, size_spec

logging_chan_name = Word(srange('[a-zA-Z0-9]') + '_-', max=63)
logging_chan_name.setName('<channel_name>')
logging_chan_name = (
Word(srange('[a-zA-Z0-9]') + '_-', max=63)
)

logging_chan_name_dequotable = (
(
Char('"').suppress() + logging_chan_name + Char('"').suppress()
)
^ (
Char("'").suppress() + logging_chan_name + Char("'").suppress()
)
^ logging_chan_name
)
logging_chan_name_dequotable.setName('<quotable_chan_name>')

# logging {
# [ channel <channel_name> {
# [ buffered <boolean>; ]
Expand Down Expand Up @@ -51,43 +83,50 @@

logging_chan_file_path_size_element = (
Literal('size').suppress()
- size_spec('size_spec')
- size_spec('size_spec') # do not ungroup this, they have optional 'K', 'M', and 'G' notation to its integer
)

logging_chan_file_path_element = (
Keyword('file').suppress()
- dequoted_path_name('path_name')('path_name')
- dequoted_path_name('path_name').setName('path_name')
- Optional(logging_chan_file_path_version_element)
- Optional(logging_chan_file_path_size_element)
)

logging_chan_syslog_facility_name = (
Literal('kern')
| Literal('user')
| Literal('mail')
| Literal('daemon')
| Literal('auth')
| Literal('syslog')
| Literal('lpr')
| Literal('news')
| Literal('uucp')
| Literal('cron')
| Literal('authpriv')
| Literal('ftp')
| Literal('local0')
| Literal('local1')
| Literal('local2')
| Literal('local3')
| Literal('local4')
| Literal('local5')
| Literal('local6')
| Literal('local7')
Keyword('kern')
^ Keyword('user')
^ Keyword('mail')
^ Keyword('daemon')
^ Keyword('auth')
^ Keyword('syslog')
^ Keyword('lpr')
^ Keyword('news')
^ Keyword('uucp')
^ Keyword('cron')
^ Keyword('authpriv')
^ Keyword('ftp')
^ Keyword('local0')
^ Keyword('local1')
^ Keyword('local2')
^ Keyword('local3')
^ Keyword('local4')
^ Keyword('local5')
^ Keyword('local6')
^ Keyword('local7')
)('facility')
logging_chan_syslog_facility_name.setName('<syslog_facility>')
logging_chan_syslog_facility_name.setName('(kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|authpriv|ftp|local1-7)')\

logging_chan_syslog_element = (
Keyword('syslog').suppress()
- logging_chan_syslog_facility_name
Group(
(
Keyword('syslog').suppress()
+ logging_chan_syslog_facility_name
)
^ (
Keyword('syslog').suppress()
)
)('syslog')
)

logging_chan_stderr_keyword = (
Expand All @@ -108,33 +147,42 @@
)

logging_chan_syslog_severity_select = (
Literal('critical')
| Literal('error')
| Literal('warning')
| Literal('notice')
| Literal('info')
| Literal('dynamic')
| (
Literal('debug').suppress()
- Optional(number_type(''))('')
)('debug')
)('')
(
(
Keyword('critical')
^ Keyword('error')
^ Keyword('warning')
^ Keyword('notice')
^ Keyword('info')
^ Keyword('dynamic')
^ (
Group(
Keyword('debug').suppress()
- (
number_type('debug_level')
)
)
)('debug')
^ Keyword('debug')('debug')
)
)
)
logging_chan_syslog_severity_select.setName('critical|error|warning|notice|info|debug <level>|dynamic')

logging_chan_syslog_severity_element = (
Group(
Keyword('severity').suppress()
- logging_chan_syslog_severity_select
)('severity')
+ semicolon
- semicolon
)('')

logging_chan_print_category_element = (
(
Keyword('print-category').suppress()
- isc_boolean('print_category')
)
+ semicolon
- semicolon
)

logging_chan_print_severity_element = (
Expand All @@ -152,14 +200,14 @@
| Keyword('local')
| isc_boolean
)('print_time')
+ semicolon
- semicolon
)

# [ buffered <boolean>; ]
logging_chan_buffered_element = (
Keyword('buffered').suppress()
- isc_boolean('buffered')
+ semicolon
- semicolon
)

logging_chan_method_option_set = (
Expand All @@ -182,58 +230,73 @@
logging_stmt_channel_set = (
Keyword('channel').suppress()
- Group(
logging_chan_name('channel_name')
+ lbrack
ungroup(logging_chan_name_dequotable)('channel_name')
- lbrack
- logging_chan_method_element
+ rbrack
)
+ semicolon
)('channel')
- rbrack
)('channels*')
- semicolon
)

logging_channel_name_series = (
OneOrMore(
logging_chan_name
+ semicolon
logging_chan_name_dequotable
- semicolon
)
)('logging_channel_name_series')
logging_channel_name_series.setName('<channel_name>; [...]')
)('channel_names')
logging_channel_name_series.setName('<dequotable_channel_name>; [...]')

# Too many ISC Bind9 categories to put here, must be future-proof.
logging_category_name = name_type
logging_category_name.setName('<category_name>')
logging_category_name = copy.deepcopy(name_type)

logging_category_name_dequotable = (
(
Combine(Char('"').suppress() + logging_category_name + Char('"').suppress())
)
^ (
Combine(Char("'").suppress() + logging_category_name + Char("'").suppress())
)
^ logging_category_name
)
logging_chan_name_dequotable.setName('<dequotable-chan-name>')

#
# CATEGORIES
#
logging_stmt_category_set = (
Keyword('category').suppress()
+ Group(
logging_category_name('category_group_name')
+ lbrack
- logging_channel_name_series('categories')
+ rbrack
)
+ semicolon
)('category_group')
(
ungroup(logging_category_name_dequotable)('category_group_name')
- lbrack
- logging_channel_name_series
- rbrack
)
)('category_groups*')
- semicolon
)

logging_stmt_set = (
logging_stmt_channel_set
| logging_stmt_category_set
^ logging_stmt_category_set
)

logging_stmt_series = (
OneOrMore(
Group(
Group(
OneOrMore(
logging_stmt_set
)
)
)('logging')
)

clause_stmt_logging_standalone = (
Keyword('logging').suppress()
- Group(
- ( # no Group() here, at most one 'logging' clause allowed.
lbrack
+ logging_stmt_series
+ rbrack
)('logging')
+ semicolon
- logging_stmt_series
- rbrack
) # no '*' here, at most one 'logging clause allowed.
- semicolon
)


Expand Down
4 changes: 3 additions & 1 deletion bind9_parser/isc_optview.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
to both options and view (but not zones)
"""
import copy

from pyparsing import Group, Keyword, OneOrMore, Literal, \
CaselessLiteral, Combine, Optional, Word, alphanums, ZeroOrMore,\
ungroup
Expand Down Expand Up @@ -90,7 +92,7 @@
)('allow-recursion-on')
).setName('allow-recursion-on <aml>;')

optview_attach_cache_name = name_type # TODO: Identify when it got obsoleted???
optview_attach_cache_name = copy.deepcopy(name_type) # TODO: Identify when it got obsoleted???
optview_attach_cache_name.setName('<cache_name>')
optview_stmt_attach_cache = (
Keyword('attach-cache').suppress()
Expand Down
11 changes: 6 additions & 5 deletions bind9_parser/isc_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Requires: pyparsing-2.4.3 (Char method)
"""
import copy
import os
import os.path
import errno
Expand Down Expand Up @@ -181,7 +182,7 @@
^ name_dquotable
)('name')
quoted_name.setName('<quoted_name>')
name_type = quotable_name
name_type = copy.deepcopy(quotable_name)

# dequotable_name
name_dedquotable = Combine(
Expand Down Expand Up @@ -238,7 +239,7 @@
^ keysecret_base
)('key_secret')
key_secret.setName('<secret_string>')
quotable_key_secret = key_secret
quotable_key_secret = copy.deepcopy(key_secret)
quotable_key_secret.setName('<quotable_key_secret')
quoted_key_secret = (
keysecret_squotable
Expand Down Expand Up @@ -867,9 +868,9 @@ def _inner(*args):
return _inner

import pyparsing
pyparsing._defaultStartDebugAction = incr_pos(pyparsing._defaultStartDebugAction)
pyparsing._defaultSuccessDebugAction = decr_pos(pyparsing._defaultSuccessDebugAction)
pyparsing._defaultExceptionDebugAction = incr_pos(pyparsing._defaultExceptionDebugAction)
# pyparsing._defaultStartDebugAction = incr_pos(pyparsing._defaultStartDebugAction)
# pyparsing._defaultSuccessDebugAction = decr_pos(pyparsing._defaultSuccessDebugAction)
#pyparsing._defaultExceptionDebugAction = incr_pos(pyparsing._defaultExceptionDebugAction)
try:
parser_element = parser_element.setDebug(True)
result = parser_element.parseString(test_strings, parseAll=True)
Expand Down
Loading

0 comments on commit 1863739

Please sign in to comment.