ossobv / asterisklint Goto Github PK
View Code? Open in Web Editor NEWAsterisk PBX configuration syntax checker
License: GNU General Public License v3.0
Asterisk PBX configuration syntax checker
License: GNU General Public License v3.0
Apparently it was broken (since py3.5?).
When i check my extensions conf, i have got an error:
func_odbc.conf:6 E_CONF_KEY_INVALID: expected valid var/object or new context, got 'writesql+'
My func_odbc.conf:
[ADD]
prefix=REPORTS
synopsis=Get report values from VAL1 and add it to the reports table
dsn=int-dsn-asterisk
writesql=INSERT INTO pbx.call_reports (values_list)
writesql+=VALUES ('${SQL_ESC(${VAL1})}')
The make update_version
call fixes the version string. We don't want to forget its call before doing the pip sdist upload.
I'm not saying that the Pattern Matching syntax is correct here, but it raised an exception
exten => _XXX[1,2,3,7,8]XXX,1,NoOp(DEBUG)
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/asterisklint/config.py", line 186, in __iter__
self.on_varset(element)
File "/usr/local/lib/python3.8/site-packages/asterisklint/dialplan.py", line 600, in on_varset
dialplanvarset = DialplanVarset.from_varset(varset)
File "/usr/local/lib/python3.8/site-packages/asterisklint/dialplan.py", line 507, in from_varset
pattern = pattern and Pattern(pattern, varset.where) or None
File "/usr/local/lib/python3.8/site-packages/asterisklint/pattern.py", line 107, in __init__
self.values = self.parse(pattern)
File "/usr/local/lib/python3.8/site-packages/asterisklint/pattern.py", line 116, in parse
return tuple([Pattern.IS_A_PATTERN] + cls.parse_pattern(raw[1:]))
File "/usr/local/lib/python3.8/site-packages/asterisklint/pattern.py", line 143, in parse_pattern
range_end = raw.index(0x5d) # ']'
ValueError: 93 is not in list
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/bin/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/usr/local/lib/python3.8/site-packages/asterisklint/main.py", line 178, in main
return command_module.main(args, envs)
File "/usr/local/lib/python3.8/site-packages/asterisklint/mainutil.py", line 35, in __call__
return self.handle_args(args)
File "/usr/local/lib/python3.8/site-packages/asterisklint/commands/dialplan-check.py", line 50, in handle_args
dialplan = next(iter(parser))
File "/usr/local/lib/python3.8/site-packages/asterisklint/config.py", line 192, in __iter__
raise ProgrammingError(str(element.where)) from exc
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: extensions.conf:4079
I already fixed the expression to:
exten => _XXX[1-378]XXX,1,NoOp(DEBUG)
The exception is not raised anymore, so the commas inside of brackets make it break.
app 'BackGround' does not have the proper Case 'Background'
But...
https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+Application_BackGround
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/asterisklint/config.py", line 186, in __iter__
self.on_varset(element)
File "/usr/local/lib/python3.6/site-packages/asterisklint/dialplan.py", line 600, in on_varset
dialplanvarset = DialplanVarset.from_varset(varset)
File "/usr/local/lib/python3.6/site-packages/asterisklint/dialplan.py", line 508, in from_varset
app = App(app, varset.where)
File "/usr/local/lib/python3.6/site-packages/asterisklint/application.py", line 111, in __init__
self.parse()
File "/usr/local/lib/python3.6/site-packages/asterisklint/application.py", line 134, in parse
self.data = self.parse_inner(self.data)
File "/usr/local/lib/python3.6/site-packages/asterisklint/application.py", line 149, in parse_inner
data = VarLoader().parse_variables(data, self.where)
File "/usr/local/lib/python3.6/site-packages/asterisklint/varfun.py", line 289, in parse_variables
inner_data, where)
File "/usr/local/lib/python3.6/site-packages/asterisklint/varfun.py", line 330, in _process_variable
return FuncLoader().process_read_function(data, where)
File "/usr/local/lib/python3.6/site-packages/asterisklint/varfun.py", line 178, in process_read_function
loaded_func = FuncLoader()._get_and_check_availability(func, where)
File "/usr/local/lib/python3.6/site-packages/asterisklint/varfun.py", line 206, in _get_and_check_availability
loaded = FuncLoader().get(func.lower())
AttributeError: 'list' object has no attribute 'lower'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/bin/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/usr/local/lib/python3.6/site-packages/asterisklint/main.py", line 178, in main
return command_module.main(args, envs)
File "/usr/local/lib/python3.6/site-packages/asterisklint/mainutil.py", line 35, in __call__
return self.handle_args(args)
File "/usr/local/lib/python3.6/site-packages/asterisklint/commands/dialplan-check.py", line 50, in handle_args
dialplan = next(iter(parser))
File "/usr/local/lib/python3.6/site-packages/asterisklint/config.py", line 192, in __iter__
raise ProgrammingError(str(element.where)) from exc
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: ./extensions.conf:1069
The line of dialplan that caused the exception
same => n,Set(is_open=${ODBC_CHECK_TIMESET_${TOUPPER(${STRFTIME(,,%a)})}(${ARG1})})
.. and make them friends by fixing a bit of both.
In func_odbc.conf
it's possible to specify general options for ODBC through the [general]
context.
However, Asterisk Lint does not seem to recognize this. These are the validation errors returned for a func_odbc.conf
with a [general]
context.
./func_odbc.conf:17 W_ODBC_BADTOKENS: odbc function 'general' should be uppercase with A-Z0-9_ only
./func_odbc.conf:22 E_CONF_KEY_INVALID: expected valid var/object or new context, got 'single_db_connection'
./func_odbc.conf:17 E_ODBC_NOSQL: a readsql and/or writesql (and insertsql) statement is required
Now that we have initial support for func_odbc SQL column counts, we could add support for (at least) counting the number of returned arguments.
E.g.
[FUNC]
readsql=SELECT a, b, c FROM table WHERE id = ${ARG1}
same => n,Set(ARRAY(LOCAL(a),LOCAL(b))=${ODBC_FUNC(1)})
; ^ E_SOMETHING: missing return value 'c'
OpenBSD 6.8
Asterisk 18.1.1
asterisklint dialplan-check extensions.conf
produces error:
extensions.conf:9 E_DP_PRIO_INVALID: invalid priority '3]XX'
Content of extensions.conf:
[general]
static=yes
writeprotect=yes
clearglobalvars=no
[globals]
[phones]
exten => _[2,3]XX,1,NoOp(Incoming call for ${EXTEN})
I have make syntax mistake - added excess comma before opening bracket in gosub:
exten => _7495XXXXXXX,1,Gosub(sub-dial,${EXTEN},1,(${SOME_VARIABLE}))
When i start asterisklint dialplan-check extensions.conf
it freeze with 100% one core cpu load and this message in console:
extensions.conf:44 E_APP_ARG_MANY: too many arguments for app 'Gosub', maximum is 3
P.S. I broke by this error your site: https://asterisklint.osso.pub/
I'm sorry! :))
Without it, for example, we get plenty of errors on standard Freepbx config:
b.com/FreePBX/core.git
Cloning into 'core'...
remote: Counting objects: 10137, done.
remote: Total 10137 (delta 0), reused 0 (delta 0), pack-reused 10137
Receiving objects: 100% (10137/10137), 6.99 MiB | 91.00 KiB/s, done.
Resolving deltas: 100% (6560/6560), done.
Checking connectivity... done.
root@as-05:~# cd core/etc/
root@as-05:~/core/etc# ../../asterisklint/scripts/asterisklint dialplan-check ./extensions.conf
./extensions.conf:29 W_PP_INCLUDE_MISSING: the #include file 'extensions_override_freepbx.conf' could not be found
./extensions.conf:30 W_PP_INCLUDE_MISSING: the #include file 'extensions_additional.conf' could not be found
./extensions.conf:31 W_PP_INCLUDE_MISSING: the #include file 'extensions_custom.conf' could not be found
./extensions.conf:35 H_WSV_CTX_BETWEEN: expected one or two lines between non-tiny contexts
./extensions.conf:99 W_DP_PRIO_BADORDER: bad priority order for pattern '_+1NXXNXXXXXX/_NXXNXXXXXX' and prio 2
./extensions.conf:101 W_DP_PRIO_BADORDER: bad priority order for pattern '_+1NXXNXXXXXX/_011NX.' and prio <unset>
./extensions.conf:105 W_DP_PRIO_BADORDER: bad priority order for pattern '_[0-9+]./_NXXNXXXXXX' and prio <unset>
./extensions.conf:107 W_DP_PRIO_BADORDER: bad priority order for pattern '_[0-9+]./_011NX.' and prio <unset>
./extensions.conf:110 W_DP_PRIO_BADORDER: bad priority order for pattern 's/_NXXNXXXXXX' and prio <unset>
./extensions.conf:112 W_DP_PRIO_BADORDER: bad priority order for pattern 's/_011NX.' and prio <unset>
./extensions.conf:148 W_APP_NEED_PARENS: app 'Answer' should have parentheses (only NoOp is exempt)
./extensions.conf:151 W_APP_BAD_CASE: app 'Playtones' does not have the proper Case 'PlayTones'
./extensions.conf:153 W_APP_NEED_PARENS: app 'Hangup' should have parentheses (only NoOp is exempt)
./extensions.conf:154 W_APP_NEED_PARENS: app 'Hangup' should have parentheses (only NoOp is exempt)
./extensions.conf:155 W_APP_NEED_PARENS: app 'Hangup' should have parentheses (only NoOp is exempt)
./extensions.conf:159 H_WSV_CTX_BETWEEN: expected one or two lines between non-tiny contexts
./extensions.conf:201 H_WSV_CTX_BETWEEN: expected one or two lines between non-tiny contexts
./extensions.conf:232 E_FUNC_MISSING: function 'DB' does not exist (or func_odbc created?)
./extensions.conf:234 W_DP_PRIO_BADORDER: bad priority order for pattern 's' and prio 200
./extensions.conf:235 W_DP_PRIO_BADORDER: bad priority order for pattern 's' and prio 300
./extensions.conf:241 W_WSH_EOL: unexpected trailing whitespace
./extensions.conf:298 E_FUNC_MISSING: function 'DB' does not exist (or func_odbc created?)
./extensions.conf:310 E_FUNC_MISSING: function 'DB_EXISTS' does not exist (or func_odbc created?)
./extensions.conf:315 E_FUNC_MISSING: function 'DB' does not exist (or func_odbc created?)
./extensions.conf:317 E_APP_MISSING: app 'Authenticate' does not exist, dialplan will halt here!
./extensions.conf:318 E_APP_MISSING: app 'AGI' does not exist, dialplan will halt here!
./extensions.conf:325 W_APP_NEED_PARENS: app 'Hangup' should have parentheses (only NoOp is exempt)
./extensions.conf:329 W_APP_NEED_PARENS: app 'Hangup' should have parentheses (only NoOp is exempt)
./extensions.conf:337 W_APP_NEED_PARENS: app 'Hangup' should have parentheses (only NoOp is exempt)
./extensions.conf:351 E_FUNC_MISSING: function 'DB' does not exist (or func_odbc created?)
./extensions.conf:353 E_APP_MISSING: app 'AGI' does not exist, dialplan will halt here!
./extensions.conf:358 W_APP_NEED_PARENS: app 'Hangup' should have parentheses (only NoOp is exempt)
./extensions.conf:372 W_APP_BAD_CASE: app 'Noop' does not have the proper Case 'NoOp'
./extensions.conf:377 H_WSV_CTX_BETWEEN: expected one or two lines between non-tiny contexts
./extensions.conf:410 W_APP_BAD_CASE: app 'Noop' does not have the proper Case 'NoOp'
./extensions.conf:411 E_FUNC_MISSING: function 'MD5' does not exist (or func_odbc created?)
./extensions.conf:415 W_APP_BAD_CASE: app 'Noop' does not have the proper Case 'NoOp'
./extensions.conf:417 E_DP_PRIO_INVALID: invalid priority 'tts+101'
./extensions.conf:427 W_APP_BAD_CASE: app 'Noop' does not have the proper Case 'NoOp'
./extensions.conf:428 E_FUNC_MISSING: function 'MD5' does not exist (or func_odbc created?)
./extensions.conf:434 E_DP_PRIO_INVALID: invalid priority 'tts+101'
./extensions.conf:443 W_APP_BAD_CASE: app 'Noop' does not have the proper Case 'NoOp'
./extensions.conf:444 E_FUNC_MISSING: function 'MD5' does not exist (or func_odbc created?)
./extensions.conf:450 E_DP_PRIO_INVALID: invalid priority 'tts+101'
./extensions.conf:459 W_APP_BAD_CASE: app 'Noop' does not have the proper Case 'NoOp'
./extensions.conf:460 E_FUNC_MISSING: function 'MD5' does not exist (or func_odbc created?)
./extensions.conf:0 H_DP_GENERAL_MISPLACED: [general] context not found or not at top of file
./extensions.conf:0 H_DP_GLOBALS_MISPLACED: [globals] context not found or not at position two
The above seems to fail because asterisk is ,-splitting very soon. You'd need a \,
instead of ,
inside the regex. Horrible.
Can be worked around by using a global for the regex.
We should check whether Ast11 does this too and what happens exactly. And then warn about comma's.
Just a couple of minor things...
extensions.conf:181 E_FUNC_MISSING: function 'VOLUME' does not exist (or func_odbc created?)
https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+Function_VOLUME
extensions.conf:121 E_APP_MISSING: app 'Milliwatt' does not exist, dialplan will halt here!
https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+Application_Milliwatt
The smaller methods kind of speak for themselves.
The pre-commit hook as-is displays a lot (arguably) irrelevant stuff if other files than changed ones trigger warnings. A possible solution would be to use the output of the following:
git diff --cached --name-only --diff-filter=ACM
Only staged changes would then trigger the dialplan-check
.
The full pre-commit file:
#!/bin/sh
export ALINT_IGNORE= # adjust as needed
for c in $(git diff --cached --name-only --diff-filter=ACM);
do
asterisklint dialplan-check /PATH/TO/extensions.conf/$c
done
ret=$?
if test $ret -ne 0; then
echo >&2
echo 'One or more dialplan syntax errors. Please fix before committing.' >&2
exit $ret
fi
exit 0
It's a staticmethod, so we can easily move it to a different ArgSeparator class.
And then split up the function into a few protected methods.
The chan_sip seems to be deprecated in favor of pjsip. Would be nice if pjsip.conf and pjsip_wizard.conf support were added to this tool.
OpenBSD 6.8
Asterisk 18.1.1
E_FUNC_MISSING: function does not exist (or func_odbc created?):
'DEVICE_STATE'
'DIALGROUP'
'DIALPLAN_EXISTS'
'PJSIP_DIAL_CONTACTS'
Links to the function docs:
https://wiki.asterisk.org/wiki/display/AST/Function_DEVICE_STATE
https://wiki.asterisk.org/wiki/display/AST/Function_DIALGROUP
https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+Function_DIALPLAN_EXISTS
https://wiki.asterisk.org/wiki/display/AST/Asterisk+15+Function_PJSIP_DIAL_CONTACTS
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: extensions_choosevoice.conf:6
Here are lines 5,6 and 7 of the offending file:
same => n,Verbose(1,${languages})
same => n,While($["${SET(languagenumber=${SHIFT(languages)})}" != ""])
same => n,Gosub(choosevoice,getlangitems,1(${languagenumber}))
And here is the error in full:
/etc/asterisk# asterisklint dialplan-check extensions.conf
func_odbc.conf:88 E_CONF_KEY_INVALID: expected valid var/object or new context, got 'syntax'
func_odbc.conf:89 W_CONF_KEY_LATE: expected varset 'synopsis' earlier, fix your ordering
func_odbc.conf:96 W_WSV_EOF: unexpected vertical space at end of file
extensions.conf:97 W_APP_BAD_CASE: app 'agi' does not have the proper Case 'AGI'
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/asterisklint/config.py", line 186, in __iter__
self.on_varset(element)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/dialplan.py", line 591, in on_varset
dialplanvarset = DialplanVarset.from_varset(varset)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/dialplan.py", line 499, in from_varset
app = App(app, varset.where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/application.py", line 111, in __init__
self.parse()
File "/usr/local/lib/python3.5/dist-packages/asterisklint/application.py", line 134, in parse
self.data = self.parse_inner(self.data)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/application.py", line 149, in parse_inner
data = VarLoader().parse_variables(data, self.where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 284, in parse_variables
inner_data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 288, in parse_variables
inner_data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 329, in _process_variable
return FuncLoader().process_read_function(data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 178, in process_read_function
loaded_func(args, where=where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/func/vall/func_logic.py", line 43, in __call__
VarLoader().parse_assignment(data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 236, in parse_assignment
dest, value = data.split('=', 1)
AttributeError: 'list' object has no attribute 'split'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/bin/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/usr/local/lib/python3.5/dist-packages/asterisklint/main.py", line 147, in main
return command_module.main(args, envs)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/mainutil.py", line 35, in __call__
return self.handle_args(args)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/commands/dialplan-check.py", line 50, in handle_args
dialplan = next(iter(parser))
File "/usr/local/lib/python3.5/dist-packages/asterisklint/config.py", line 192, in __iter__
raise ProgrammingError(str(element.where)) from exc
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: extensions_choosevoice.conf:6
root@televox:/etc/asterisk# asterisklint dialplan-check extensions.conf
func_odbc.conf:88 E_CONF_KEY_INVALID: expected valid var/object or new context, got 'syntax'
func_odbc.conf:89 W_CONF_KEY_LATE: expected varset 'synopsis' earlier, fix your ordering
func_odbc.conf:96 W_WSV_EOF: unexpected vertical space at end of file
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/asterisklint/config.py", line 186, in __iter__
self.on_varset(element)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/dialplan.py", line 591, in on_varset
dialplanvarset = DialplanVarset.from_varset(varset)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/dialplan.py", line 499, in from_varset
app = App(app, varset.where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/application.py", line 111, in __init__
self.parse()
File "/usr/local/lib/python3.5/dist-packages/asterisklint/application.py", line 134, in parse
self.data = self.parse_inner(self.data)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/application.py", line 149, in parse_inner
data = VarLoader().parse_variables(data, self.where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 284, in parse_variables
inner_data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 288, in parse_variables
inner_data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 329, in _process_variable
return FuncLoader().process_read_function(data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 178, in process_read_function
loaded_func(args, where=where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/func/vall/func_logic.py", line 43, in __call__
VarLoader().parse_assignment(data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 236, in parse_assignment
dest, value = data.split('=', 1)
AttributeError: 'list' object has no attribute 'split'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/bin/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/usr/local/lib/python3.5/dist-packages/asterisklint/main.py", line 147, in main
return command_module.main(args, envs)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/mainutil.py", line 35, in __call__
return self.handle_args(args)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/commands/dialplan-check.py", line 50, in handle_args
dialplan = next(iter(parser))
File "/usr/local/lib/python3.5/dist-packages/asterisklint/config.py", line 192, in __iter__
raise ProgrammingError(str(element.where)) from exc
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: extensions_choosevoice.conf:6```
Hello!
Can you add support for ansible jinja2 template syntax (for example detect double brace as string)?
I use ansible for change config files of asterisk and linter with this files works incorrect:
There is link on other examples
Alternative idea: add support for line ignore comment, like it works in eslint:
{{ some incorrect syntax line }} # asterisklint-disable-line
// eslint-disable-line
OpenBSD 6.8
Asterisk 18.1.1
asterisklint dialplan-check extensions.conf
produces a python error:
Traceback (most recent call last):
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/config.py", line 186, in __iter__
self.on_varset(element)
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/dialplan.py", line 600, in on_varset
dialplanvarset = DialplanVarset.from_varset(varset)
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/dialplan.py", line 507, in from_varset
pattern = pattern and Pattern(pattern, varset.where) or None
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/pattern.py", line 107, in __init__
self.values = self.parse(pattern)
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/pattern.py", line 116, in parse
return tuple([Pattern.IS_A_PATTERN] + cls.parse_pattern(raw[1:]))
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/pattern.py", line 143, in parse_pattern
range_end = raw.index(0x5d) # ']'
ValueError: 93 is not in list
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/ugisu/.pyenv/versions/3.8.0/bin/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/main.py", line 178, in main
return command_module.main(args, envs)
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/mainutil.py", line 35, in __call__
return self.handle_args(args)
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/commands/dialplan-check.py", line 50, in handle_args
dialplan = next(iter(parser))
File "/Users/ugisu/.pyenv/versions/3.8.0/lib/python3.8/site-packages/asterisklint/config.py", line 192, in __iter__
raise ProgrammingError(str(element.where)) from exc
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: extensions.conf:15
if extensions.conf has this content:
[general]
static=yes
writeprotect=yes
clearglobalvars=no
[globals]
[phones]
exten => _00XX.,1,NoOp(Outgoing call to +${EXTEN:2})
same => n,Set(zeroesExten=+${EXTEN:2})
same => n,Gosub(set-caller-id,s,1)
same => n,Dial(PJSIP/${zeroesExten}@sometrunk)
same => n,Hangup()
exten => _004490[0,1,6].,1,NoOp(Some number ${EXTEN})
same => n,Wait(1)
same => n,Playback(t26/premium-numbers)
same => n,Hangup()
[set-caller-id]
exten => s,1,NoOp(Set caller ID)
same => n,Set(caller_ext=${CALLERID(num)})
same => n,ExecIf($[${REGEX("^2[0-9][0-9]$" ${caller_ext})} = 1]?Set(CALLERID(num)=+441234567890))
same => n,Return()
if we change exten => _004490[0,1,6].,1,NoOp(Some number ${EXTEN})
with exten => _004490(0|1|6).,1,NoOp(Some number ${EXTEN})
there are no errors, but the regex in Asterisk is not working.
/usr/local/CHANGES.rst
after pip3 install of 0.3.0.
That's not the right location..
Issue observed on johnc-pbx2.
Summary: AssertionError: CPLAYBACKOFFSET=0
CPLAYBACKOFFSET=0
is indeed wrong, but makes asterisklint crash.
Offending code
exten => s,1,Verbose(1,Context:${CONTEXT} Extension:${EXTEN} foldercount:${foldercount} numberOfTracks:${numberOfTracks} currentTrackFileName:${currentTrackFileName} pathDepth:${pathDepth} scanPath:${scanPath} CPLAYBACKOFFSET:${CPLAYBACKOFFSET=0})
Full output
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/asterisklint/config.py", line 186, in __iter__
self.on_varset(element)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/dialplan.py", line 588, in on_varset
dialplanvarset = DialplanVarset.from_varset(varset)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/dialplan.py", line 496, in from_varset
app = App(app, varset.where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/application.py", line 120, in __init__
self.parse()
File "/usr/local/lib/python3.5/dist-packages/asterisklint/application.py", line 142, in parse
self.data = self.parse_inner(self.data)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/application.py", line 164, in parse_inner
data = VarLoader().parse_variables(data, self.where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 217, in parse_variables
inner_data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 267, in _process_variable
self.count_var(data, where)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/varfun.py", line 305, in count_var
for i in varname), varname
AssertionError: CPLAYBACKOFFSET=0
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/bin/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/usr/local/lib/python3.5/dist-packages/asterisklint/main.py", line 147, in main
return command_module.main(args, envs)
File "/usr/local/lib/python3.5/dist-packages/asterisklint/commands/modules-show.py", line 74, in main
dialplan = next(iter(parser))
File "/usr/local/lib/python3.5/dist-packages/asterisklint/config.py", line 192, in __iter__
raise ProgrammingError(str(element.where)) from exc
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: ./extensions_star_help_handler.conf:102```
exten => 151,hint,Custom:test,CustomPresence:mypresence01
leads to
./dialplan.conf:70 I_NOTIMPL_HINT: the dialplan hint directive has not been implemented yet
exten = 151,hint,Custom:test,CustomPresence:mypresence01
which is a valid Asterisk syntax for defining hints
leads to a crash:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/asterisklint/config.py", line 186, in __iter__
self.on_varset(element)
File "/usr/local/lib/python3.6/dist-packages/asterisklint/dialplan.py", line 600, in on_varset
dialplanvarset = DialplanVarset.from_varset(varset)
File "/usr/local/lib/python3.6/dist-packages/asterisklint/dialplan.py", line 473, in from_varset
assert varset.arrow # W_ARROW
AssertionError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/bin/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/usr/local/lib/python3.6/dist-packages/asterisklint/main.py", line 178, in main
return command_module.main(args, envs)
File "/usr/local/lib/python3.6/dist-packages/asterisklint/mainutil.py", line 35, in __call__
return self.handle_args(args)
File "/usr/local/lib/python3.6/dist-packages/asterisklint/commands/dialplan-check.py", line 50, in handle_args
dialplan = next(iter(parser))
File "/usr/local/lib/python3.6/dist-packages/asterisklint/config.py", line 192, in __iter__
raise ProgrammingError(str(element.where)) from exc
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: ./dialplan.conf:12
asterisklint will throw an error when using NoCDR() in the dialplan, even when module app_cdr.so is loaded:
/etc/asterisk# asterisk -rx 'module show' | grep app_cdr
app_cdr.so Tell Asterisk to not maintain a CDR for 0 Running core
/etc/asterisk# grep NoCDR extensions.conf
exten => _X.,1,NoCDR()
/etc/asterisk# git commit -a
/etc/asterisk/extensions.conf:xxx E_APP_MISSING: app 'NoCDR' does not exist, dialplan will halt here!
(using asterisklint version 0.2.1)
These bits can be easily moved to a separate splitting method.
if rest[0] == '"' and rest[-1] == '"':
...
And this can be moved to a rest-extracting method:
if not rest or ord(rest[0]) > 32:
E_CONF_BAD_LINE(where, startswith=text[0:16])
return
for idx, ch in enumerate(rest):
if ord(ch) > 32:
break
else:
# Nothing after the #include/#tryinclude/#exec.
E_CONF_BAD_LINE(where, startswith=text[0:16])
return
if (not all(i == ' ' for i in rest[0:idx]) and
not all(i == '\t' for i in rest[0:idx])):
W_WSH_CTRL(where)
rest = rest[idx:]
In the README, it says:
Add functions DB, DB_EXISTS, MD5 (as used in FreePBX dialplan).
Add apps Authenticate, AGI (as used in FreePBX dialplan).
However, these are pretty core Asterisk functions and apps.
def __call__(self, args, envs):
args = self.parse_args(args)
return self.handle_args(args)
Should either use it or lose it.
If we use annotate and annotate --collapse as idempotent commands, we can make func_odbc editing a lot easier. (We probably don't want a separate func_odbc-collapse command, seeing that the functionality it so closely tied.)
Also: if possible, we'll want an "edit-inline" flag, so we can rewrite the files instead of spitting out the output. Otherwise #includes won't be editable.
There is no error detection for the improper excess :
after ?
./extensions.conf:1966 E_FUNC_MISSING: function 'AUDIOHOOK_INHERIT' does not exist (or func_odbc created?)
I know that Authenticate
and AGI
is on the to-do list, but the rest are fairly standard, long-standing basic everyday applications. Not whining because this is a great app, just pointing it out!
; WARNING: The following unknown applications were seen:
; (none), ControlPlayback, EndWhile, ExitWhile, VMSayName, While, agi
./extensions.conf:480 E_APP_ARG_MANY: too many arguments for app 'Originate', maximum is 6
^-
Originate(tech_data,type,arg1[,arg2[,arg3[,timeout[,options]]]])
(ast 16)
Possibly protected (single underscore) functions to start with.
[context]
exten => _X!,1,Set(i18n_region=default)
exten => _X!,2,Return()
[context]
exten => 27,1,Set(i18n_region=ZA)
exten => 31,1,Set(i18n_region=NL)
exten => 32,1,Set(i18n_region=BE)
exten => _X!,1,Set(i18n_region=default)
exten => _X!,2,Return()
How should we handle this? Fix VG context to drop older context if new one is found? How does Ast handle it?
Imagine, if you will, that Asterisk 20 introduces a new, optional syntax to extensions.conf. Now imagine that, by mistake, I put a new-syntax extensions.conf in my Asterisk 18 installation. It is invalid, but asterisklint will flag it as valid. My suggestion is to take an optional argument, saying what Asterisk version we're checking against. This could apply to other subcommands too, not only dialplan-check
.
asterisklint dialplan-check -a 18 ~/mystagindir/extensions.conf
Or
asterisklint -a 18 dialplan-check ~/mystagindir/extensions.conf
Could also be an environment variable:
ALINT_ASTVER=18 asterisklint dialplan-check ~/mystagindir/extensions.conf
Make two commands: func_odbc-annotate and func_odbc-collapse.
The first one should convert this:
; somefunc is awesome
[SOMEFUNC]
readsql=SELECT id AS col1, 'hardcoded' AS col2 FROM table
into this:
; > ODBC_SOMEFUNC
; >
; > read return values: (1) col1, (2) col2
[SOMEFUNC]
readsql=SELECT id AS col1, 'hardcoded' AS col2
FROM table
and the second one should convert it back to:
; > ODBC_SOMEFUNC
; >
; > read return values: (1) col1, (2) col2
; somefunc is awesome
[SOMEFUNC]
readsql=SELECT id AS col1, 'hardcoded' AS col2 FROM table
This makes for easier editing of long SQL statements.
We have a partial implementation which right now spits out sql format:
[ACCOUNT_ZIPCODE]
;; ACCOUNT_ZIPCODE returns the zipcode for the account that is placing a call.
prefix=MY
readhandle=my_db
readsql=SELECT zip_code FROM account_account WHERE account_id = '${SQL_ESC(${ARG1})}'
becomes:
-- MY_ACCOUNT_ZIPCODE
-- .
-- FUNCTION TYPE: read
-- COLUMNS:
-- 1. zip_code
SELECT zip_code
FROM account_account
WHERE account_id = '${SQL_ESC(${ARG1})}';
@wdoekes Please reach out to me. You deserve a little token of my appreciation.
The asterisklint don't know about PJSIP_HEADER application?
I see references to "hooks" in one or two issues but I couldn't actually find anything. Since I use pre-commit in most of my projects, I went ahead and wrote some first-class pre-commit hooks for it. It just mirrors the current version of asterisklint so it should track that whenever you make a new release. We've been waiting (and waiting) for a certain project to spring loose but I got busy waiting and haven't actually touched it for a while. You can try it just like any of the usual python/cmake/other hooks here: https://github.com/VCTLabs/asterisklint-hooks
Any feedback is welcome - thanks!
And when it's in its own class, we can split it up into a couple of methods.
walter@walter-dev:0:~/asterisklint$ ./scripts/asterisklint dialplan-check bug.conf
bug.conf:0 H_DP_GENERAL_MISPLACED: [general] context not found or not at top of file
bug.conf:0 H_DP_GLOBALS_MISPLACED: [globals] context not found or not at position two
Traceback (most recent call last):
File "./scripts/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/home/walter/asterisklint/asterisklint/main.py", line 147, in main
return command_module.main(args, envs)
File "/home/walter/asterisklint/asterisklint/commands/dialplan-check.py", line 49, in main
dialplan.walk_jump_destinations()
File "/home/walter/asterisklint/asterisklint/dialplan.py", line 181, in walk_jump_destinations
extension, priority)
File "/home/walter/asterisklint/asterisklint/dialplan.py", line 281, in match_pattern
if pattern.matches_extension(extension):
File "/home/walter/asterisklint/asterisklint/pattern.py", line 375, in matches_extension
value = self.values[i + 2]
UnboundLocalError: local variable 'i' referenced before assignment
walter@walter-dev:1:~/asterisklint$ cat bug.conf
[context]
exten => s,1,GotoIf($["${CALLERID(num):0:1}"="+"]?${EXTEN:1},1) ; strip + if it is there
_[X,t,i],1,Goto(scanner,s,1)
gets a warning of exten => 6 E_DP_PRIO_INVALID: invalid priority 't'
However https://wiki.asterisk.org/wiki/display/AST/Special+Dialplan+Extensions says that:
t: Response timeout extension
When the caller waits too long before entering a response to the Background() or WaitExten() applications, and there are no more priorities in the current extension, the call is sent to the t extension.
This sample extensions.conf
[macro-callerid-name-shorten]
exten => s,1,Set(CALLERID(name)=${CALLERID(name):0:${ARG1}})
causes an exception in asterisklint
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/asterisklint/config.py", line 186, in __iter__
self.on_varset(element)
File "/usr/local/lib/python3.9/site-packages/asterisklint/dialplan.py", line 600, in on_varset
dialplanvarset = DialplanVarset.from_varset(varset)
File "/usr/local/lib/python3.9/site-packages/asterisklint/dialplan.py", line 508, in from_varset
app = App(app, varset.where)
File "/usr/local/lib/python3.9/site-packages/asterisklint/application.py", line 111, in __init__
self.parse()
File "/usr/local/lib/python3.9/site-packages/asterisklint/application.py", line 134, in parse
self.data = self.parse_inner(self.data)
File "/usr/local/lib/python3.9/site-packages/asterisklint/application.py", line 149, in parse_inner
data = VarLoader().parse_variables(data, self.where)
File "/usr/local/lib/python3.9/site-packages/asterisklint/varfun.py", line 288, in parse_variables
inner_data = self._process_variable(
File "/usr/local/lib/python3.9/site-packages/asterisklint/varfun.py", line 330, in _process_variable
return FuncLoader().process_read_function(data, where)
File "/usr/local/lib/python3.9/site-packages/asterisklint/varfun.py", line 182, in process_read_function
return ReadFuncSlice(func, args, start=start, length=length)
File "/usr/local/lib/python3.9/site-packages/asterisklint/variable.py", line 257, in __init__
if length < 0:
TypeError: '<' not supported between instances of 'Var' and 'int'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/bin/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/usr/local/lib/python3.9/site-packages/asterisklint/main.py", line 178, in main
return command_module.main(args, envs)
File "/usr/local/lib/python3.9/site-packages/asterisklint/mainutil.py", line 35, in __call__
return self.handle_args(args)
File "/usr/local/lib/python3.9/site-packages/asterisklint/commands/dialplan-check.py", line 50, in handle_args
dialplan = next(iter(parser))
File "/usr/local/lib/python3.9/site-packages/asterisklint/config.py", line 192, in __iter__
raise ProgrammingError(str(element.where)) from exc
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: extensions.conf:2
Replacing ${ARG1}
with a hardcoded integer works as expected, but for my logic, it must be a variable.
I can't find a decent workaround as wrapping ARG1 with TRUNC and MATH function also produce similar comparison exceptions but different instances instead of 'Var'
, 'ReadFunc'
and 'Expr'
respectively.
Testing as in running as a pre-commit hook on the example configs in Asterisk repo results in:
$ pre-commit try-repo ../mirrors-asterisklint dialplan-check --verbose --all-files
[WARNING] Creating temporary repo with uncommitted changes...
===============================================================================
Using config:
===============================================================================
repos:
- repo: /tmp/tmpy_9oi7z_/shadow-repo
rev: a0a794368016cda785cef32e75de44de13982d18
hooks:
- id: dialplan-check
===============================================================================
[INFO] Initializing environment for /tmp/tmpy_9oi7z_/shadow-repo.
[INFO] Installing environment for /tmp/tmpy_9oi7z_/shadow-repo.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
dialplan-check...........................................................Failed
- hook id: dialplan-check
- duration: 0.15s
- exit code: 1
configs/basic-pbx/extensions.conf:1 H_DP_GLOBALS_MISPLACED: [globals] context not found or not at position two
configs/basic-pbx/extensions.conf:9 W_WSH_VARSET: expected no horizontal whitespace around equals operator
Traceback (most recent call last):
File "/tmp/tmpy_9oi7z_/repo_urfu3v9/py_env-python3.9/lib/python3.9/site-packages/asterisklint/config.py", line 186, in __iter__
self.on_varset(element)
File "/tmp/tmpy_9oi7z_/repo_urfu3v9/py_env-python3.9/lib/python3.9/site-packages/asterisklint/dialplan.py", line 600, in on_varset
dialplanvarset = DialplanVarset.from_varset(varset)
File "/tmp/tmpy_9oi7z_/repo_urfu3v9/py_env-python3.9/lib/python3.9/site-packages/asterisklint/dialplan.py", line 473, in from_varset
assert varset.arrow # W_ARROW
AssertionError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/tmp/tmpy_9oi7z_/repo_urfu3v9/py_env-python3.9/bin/asterisklint", line 34, in <module>
sys.exit(main(sys.argv[1:], os.environ))
File "/tmp/tmpy_9oi7z_/repo_urfu3v9/py_env-python3.9/lib/python3.9/site-packages/asterisklint/main.py", line 178, in main
return command_module.main(args, envs)
File "/tmp/tmpy_9oi7z_/repo_urfu3v9/py_env-python3.9/lib/python3.9/site-packages/asterisklint/mainutil.py", line 35, in __call__
return self.handle_args(args)
File "/tmp/tmpy_9oi7z_/repo_urfu3v9/py_env-python3.9/lib/python3.9/site-packages/asterisklint/commands/dialplan-check.py", line 50, in handle_args
dialplan = next(iter(parser))
File "/tmp/tmpy_9oi7z_/repo_urfu3v9/py_env-python3.9/lib/python3.9/site-packages/asterisklint/config.py", line 192, in __iter__
raise ProgrammingError(str(element.where)) from exc
asterisklint.config.ProgrammingError: An unexpected exception was raised. This is most likely a bug in the asterisklint library. If you can reproduce the problem and file an issue on the bug tracker, that would be nice. Further info: configs/basic-pbx/extensions.conf:9
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.