Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Kevin Lyda
chkcrontab
Commits
66955b6f
Commit
66955b6f
authored
Jun 10, 2012
by
Kevin Lyda
💬
Browse files
More pylint placating.
Also added some dist_clean dirs to remove and info on using coverage.
parent
cb233338
Changes
3
Hide whitespace changes
Inline
Side-by-side
README.rst
View file @
66955b6f
...
...
@@ -32,6 +32,10 @@ Contributions are welcome! Please add unit tests for new features
or bug fixes. To run all the unit tests run ``./setup test``.
If you have `tox`_ installed, just run ``tox``.
You can review `coverage`_ of added tests by running
``coverage run setup.py test`` and then running
``coverage report -m``.
Note that tests are run on `Travis`_ for all supported python
versions whenever the tree on github is pushed to.
...
...
@@ -54,5 +58,6 @@ Credits
- `Kevin Lyda`_: Who got burned one too many times by broken crontabs.
.. _`tox`: http://pypi.python.org/pypi/tox
.. _`coverage`: http://pypi.python.org/pypi/coverage
.. _`Travis`: http://travis-ci.org/#!/lyda/chkcrontab
.. _`Kevin Lyda`: https://github.com/lyda
chkcrontab_lib.py
View file @
66955b6f
...
...
@@ -58,7 +58,8 @@ A brief description of each class and function:
cron line.
Logging class to pretty-print output:
LogCounter: A logging class that provides a summary of warnings and errors.
LogCounter: A logging class that provides a summary of warnings and
errors.
Putting it all together:
CheckCrontab: Checks the a crontab file.
...
...
@@ -118,7 +119,8 @@ class FSM(object):
if
state
not
in
self
.
states
:
self
.
states
[
state
]
=
{}
self
.
states
[
state
].
update
([(
char
,
(
action
,
next_state
))
for
char
in
chars
])
self
.
states
[
state
].
update
([(
char
,
(
action
,
next_state
))
for
char
in
chars
])
def
AddEndState
(
self
,
state
,
action
):
"""Handle the end state of the FSM.
...
...
@@ -168,63 +170,75 @@ class FSM(object):
return
data_out
def
ActionTime
(
data_out
,
char
):
def
action_time
(
data_out
,
char
):
"""Add a char to time."""
data_out
[
'time'
]
+=
char
def
ActionStar
(
data_out
,
char
):
def
action_star
(
data_out
,
char
):
"""Add a char to time."""
data_out
[
'time'
]
=
char
def
ActionDash
(
data_out
,
unused_char
):
def
action_dash
(
data_out
,
unused_char
):
"""Move time to range, reset time."""
data_out
[
'range'
]
=
data_out
[
'time'
]
data_out
[
'time'
]
=
''
def
ActionStep
(
data_out
,
char
):
def
action_step
(
data_out
,
char
):
"""Add a char to step."""
data_out
[
'step'
]
+=
char
def
ActionNoop
(
unused_data_out
,
unused_char
):
def
action_noop
(
unused_data_out
,
unused_char
):
"""Do nothing."""
pass
def
ActionTimeComma
(
data_out
,
unused_char
=
''
):
def
action_time_comma
(
data_out
,
unused_char
=
''
):
"""Move time to cron_times, reset time."""
data_out
[
'cron_times'
].
append
(
CTTime
(
int
(
data_out
[
'time'
])))
data_out
[
'time'
]
=
''
def
ActionStarComma
(
data_out
,
unused_char
=
''
):
def
action_star_comma
(
data_out
,
unused_char
=
''
):
"""Set cron_times, reset time."""
data_out
[
'cron_times'
].
append
(
CTStar
())
data_out
[
'time'
]
=
''
def
ActionStarStepComma
(
data_out
,
unused_char
=
''
):
def
action_star_step_comma
(
data_out
,
unused_char
=
''
):
"""Set cron_times, reset time & step."""
data_out
[
'cron_times'
].
append
(
CTStarStep
(
int
(
data_out
[
'step'
])))
data_out
[
'time'
]
=
''
data_out
[
'step'
]
=
''
def
ActionTextComma
(
data_out
,
unused_char
=
''
):
def
action_text_comma
(
data_out
,
unused_char
=
''
):
"""Set cron_times from time, reset time."""
data_out
[
'cron_times'
].
append
(
CTText
(
data_out
[
'time'
]))
data_out
[
'time'
]
=
''
def
ActionRangeComma
(
data_out
,
unused_char
=
''
):
def
action_range_comma
(
data_out
,
unused_char
=
''
):
"""Set cron_times from range & time, reset range & time."""
data_out
[
'cron_times'
].
append
(
CTRange
(
int
(
data_out
[
'range'
]),
int
(
data_out
[
'time'
])))
data_out
[
'range'
]
=
''
data_out
[
'time'
]
=
''
def
ActionTextRangeComma
(
data_out
,
unused_char
=
''
):
def
action_text_range_comma
(
data_out
,
unused_char
=
''
):
"""Set cron_times from range & time, reset range & time."""
data_out
[
'cron_times'
].
append
(
CTTextRange
(
data_out
[
'range'
],
data_out
[
'time'
]))
data_out
[
'range'
]
=
''
data_out
[
'time'
]
=
''
def
ActionRangeStepComma
(
data_out
,
unused_char
=
''
):
def
action_range_step_comma
(
data_out
,
unused_char
=
''
):
"""Set cron_times from range, time & step, reset range, time & step."""
data_out
[
'cron_times'
].
append
(
CTRangeStep
(
int
(
data_out
[
'range'
]),
int
(
data_out
[
'time'
]),
int
(
data_out
[
'step'
])))
...
...
@@ -233,7 +247,8 @@ def ActionRangeStepComma(data_out, unused_char=''):
data_out
[
'step'
]
=
''
def
ActionTextRangeStepComma
(
data_out
,
unused_char
=
''
):
def
action_text_range_step_comma
(
data_out
,
unused_char
=
''
):
"""Set cron_times from range, time & step, reset range, time & step."""
data_out
[
'cron_times'
].
append
(
CTTextRangeStep
(
data_out
[
'range'
],
data_out
[
'time'
],
int
(
data_out
[
'step'
])))
...
...
@@ -254,59 +269,61 @@ def InitCronFSM():
'cron_times'
:
[]}))
# Case: *
fsm
.
AddTransition
(
'*'
,
'start'
,
A
ction
S
tar
,
'star'
)
fsm
.
AddTransition
(
'*'
,
'next'
,
A
ction
S
tar
,
'star'
)
fsm
.
AddEndState
(
'star'
,
A
ction
S
tar
C
omma
)
fsm
.
AddTransition
(
','
,
'star'
,
A
ction
S
tar
C
omma
,
'next'
)
fsm
.
AddTransition
(
'*'
,
'start'
,
a
ction
_s
tar
,
'star'
)
fsm
.
AddTransition
(
'*'
,
'next'
,
a
ction
_s
tar
,
'star'
)
fsm
.
AddEndState
(
'star'
,
a
ction
_s
tar
_c
omma
)
fsm
.
AddTransition
(
','
,
'star'
,
a
ction
_s
tar
_c
omma
,
'next'
)
# Case: */<number>
fsm
.
AddTransition
(
'/'
,
'star'
,
ActionNoop
,
'start_star_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'start_star_step'
,
ActionStep
,
'star_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'star_step'
,
ActionStep
,
'star_step'
)
fsm
.
AddEndState
(
'star_step'
,
ActionStarStepComma
)
fsm
.
AddTransition
(
','
,
'star_step'
,
ActionStarStepComma
,
'next'
)
fsm
.
AddTransition
(
'/'
,
'star'
,
action_noop
,
'start_star_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'start_star_step'
,
action_step
,
'star_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'star_step'
,
action_step
,
'star_step'
)
fsm
.
AddEndState
(
'star_step'
,
action_star_step_comma
)
fsm
.
AddTransition
(
','
,
'star_step'
,
action_star_step_comma
,
'next'
)
# Case: <number>
fsm
.
AddTransition
(
string
.
digits
,
'start'
,
A
ction
T
ime
,
'time'
)
fsm
.
AddTransition
(
string
.
digits
,
'next'
,
A
ction
T
ime
,
'time'
)
fsm
.
AddTransition
(
string
.
digits
,
'time'
,
A
ction
T
ime
,
'time'
)
fsm
.
AddEndState
(
'time'
,
A
ction
T
ime
C
omma
)
fsm
.
AddTransition
(
','
,
'time'
,
A
ction
T
ime
C
omma
,
'next'
)
fsm
.
AddTransition
(
string
.
digits
,
'start'
,
a
ction
_t
ime
,
'time'
)
fsm
.
AddTransition
(
string
.
digits
,
'next'
,
a
ction
_t
ime
,
'time'
)
fsm
.
AddTransition
(
string
.
digits
,
'time'
,
a
ction
_t
ime
,
'time'
)
fsm
.
AddEndState
(
'time'
,
a
ction
_t
ime
_c
omma
)
fsm
.
AddTransition
(
','
,
'time'
,
a
ction
_t
ime
_c
omma
,
'next'
)
# Case: <number>-<number>
fsm
.
AddTransition
(
'-'
,
'time'
,
A
ction
D
ash
,
'start_range'
)
fsm
.
AddTransition
(
string
.
digits
,
'start_range'
,
A
ction
T
ime
,
'range'
)
fsm
.
AddTransition
(
string
.
digits
,
'range'
,
A
ction
T
ime
,
'range'
)
fsm
.
AddEndState
(
'range'
,
A
ction
R
ange
C
omma
)
fsm
.
AddTransition
(
','
,
'range'
,
A
ction
R
ange
C
omma
,
'next'
)
fsm
.
AddTransition
(
'-'
,
'time'
,
a
ction
_d
ash
,
'start_range'
)
fsm
.
AddTransition
(
string
.
digits
,
'start_range'
,
a
ction
_t
ime
,
'range'
)
fsm
.
AddTransition
(
string
.
digits
,
'range'
,
a
ction
_t
ime
,
'range'
)
fsm
.
AddEndState
(
'range'
,
a
ction
_r
ange
_c
omma
)
fsm
.
AddTransition
(
','
,
'range'
,
a
ction
_r
ange
_c
omma
,
'next'
)
# Case: <number>-<number>/<number>
fsm
.
AddTransition
(
'/'
,
'range'
,
A
ction
N
oop
,
'start_range_step'
)
fsm
.
AddTransition
(
'/'
,
'range'
,
a
ction
_n
oop
,
'start_range_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'start_range_step'
,
A
ction
S
tep
,
'range_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'range_step'
,
A
ction
S
tep
,
'range_step'
)
fsm
.
AddEndState
(
'range_step'
,
A
ction
R
ange
S
tep
C
omma
)
fsm
.
AddTransition
(
','
,
'range_step'
,
A
ction
R
ange
S
tep
C
omma
,
'next'
)
a
ction
_s
tep
,
'range_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'range_step'
,
a
ction
_s
tep
,
'range_step'
)
fsm
.
AddEndState
(
'range_step'
,
a
ction
_r
ange
_s
tep
_c
omma
)
fsm
.
AddTransition
(
','
,
'range_step'
,
a
ction
_r
ange
_s
tep
_c
omma
,
'next'
)
# Case: <text>
fsm
.
AddTransition
(
string
.
ascii_letters
,
'start'
,
A
ction
T
ime
,
'text'
)
fsm
.
AddTransition
(
string
.
ascii_letters
,
'next'
,
A
ction
T
ime
,
'text'
)
fsm
.
AddTransition
(
string
.
ascii_letters
,
'text'
,
A
ction
T
ime
,
'text'
)
fsm
.
AddEndState
(
'text'
,
A
ction
T
ext
C
omma
)
fsm
.
AddTransition
(
','
,
'text'
,
A
ction
T
ext
C
omma
,
'next'
)
fsm
.
AddTransition
(
string
.
ascii_letters
,
'start'
,
a
ction
_t
ime
,
'text'
)
fsm
.
AddTransition
(
string
.
ascii_letters
,
'next'
,
a
ction
_t
ime
,
'text'
)
fsm
.
AddTransition
(
string
.
ascii_letters
,
'text'
,
a
ction
_t
ime
,
'text'
)
fsm
.
AddEndState
(
'text'
,
a
ction
_t
ext
_c
omma
)
fsm
.
AddTransition
(
','
,
'text'
,
a
ction
_t
ext
_c
omma
,
'next'
)
# Case: <text>-<text>
fsm
.
AddTransition
(
'-'
,
'text'
,
A
ction
D
ash
,
'start_text_range'
)
fsm
.
AddTransition
(
string
.
ascii_letters
,
'start_text_range'
,
A
ction
T
ime
,
fsm
.
AddTransition
(
'-'
,
'text'
,
a
ction
_d
ash
,
'start_text_range'
)
fsm
.
AddTransition
(
string
.
ascii_letters
,
'start_text_range'
,
a
ction
_t
ime
,
'text_range'
)
fsm
.
AddTransition
(
string
.
ascii_letters
,
'text_range'
,
A
ction
T
ime
,
fsm
.
AddTransition
(
string
.
ascii_letters
,
'text_range'
,
a
ction
_t
ime
,
'text_range'
)
fsm
.
AddEndState
(
'text_range'
,
A
ction
T
ext
R
ange
C
omma
)
fsm
.
AddTransition
(
','
,
'text_range'
,
A
ction
T
ext
R
ange
C
omma
,
'next'
)
fsm
.
AddEndState
(
'text_range'
,
a
ction
_t
ext
_r
ange
_c
omma
)
fsm
.
AddTransition
(
','
,
'text_range'
,
a
ction
_t
ext
_r
ange
_c
omma
,
'next'
)
# Case: <text>-<text>/<text>
fsm
.
AddTransition
(
'/'
,
'text_range'
,
A
ction
N
oop
,
'start_text_range_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'start_text_range_step'
,
A
ction
S
tep
,
fsm
.
AddTransition
(
'/'
,
'text_range'
,
a
ction
_n
oop
,
'start_text_range_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'start_text_range_step'
,
a
ction
_s
tep
,
'text_range_step'
)
fsm
.
AddTransition
(
string
.
digits
,
'text_range_step'
,
A
ction
S
tep
,
fsm
.
AddTransition
(
string
.
digits
,
'text_range_step'
,
a
ction
_s
tep
,
'text_range_step'
)
fsm
.
AddEndState
(
'text_range_step'
,
ActionTextRangeStepComma
)
fsm
.
AddTransition
(
','
,
'text_range_step'
,
ActionTextRangeStepComma
,
'next'
)
fsm
.
AddEndState
(
'text_range_step'
,
action_text_range_step_comma
)
fsm
.
AddTransition
(
','
,
'text_range_step'
,
action_text_range_step_comma
,
'next'
)
return
fsm
...
...
@@ -315,25 +332,33 @@ class CronTimeField(object):
"""CronTimeField superclass for various time specifiers in cron fields."""
def
__init__
(
self
):
pass
self
.
_text
=
None
self
.
_kind
=
None
self
.
_start
=
None
self
.
_end
=
None
self
.
_step
=
None
def
__str__
(
self
):
return
self
.
_text
@
property
def
kind
(
self
):
"""Kind field."""
return
self
.
_kind
@
property
def
start
(
self
):
"""Start value of this field."""
return
self
.
_start
@
property
def
end
(
self
):
"""End value of this field."""
return
self
.
_end
@
property
def
step
(
self
):
"""Step for this field."""
return
self
.
_step
def
CheckLowStep
(
self
,
diagnostics
,
cron_time_field
):
...
...
@@ -497,6 +522,7 @@ class CTText(CronTimeField):
self
.
_text
=
'%s'
%
start_time
def
GetDiagnostics
(
self
,
cron_time_field
):
"""Checks for issues with a text field."""
diagnostics
=
[]
self
.
CheckValidText
(
diagnostics
,
self
.
_start
,
cron_time_field
)
return
diagnostics
...
...
@@ -551,11 +577,14 @@ class CronTimeFieldLimit(object):
self
.
min_time
=
min_time
self
.
max_time
=
max_time
self
.
valid_text
=
valid_text
self
.
_name
=
None
def
_GetName
(
self
):
"""Return the name."""
return
self
.
_name
def
_SetName
(
self
,
name
):
"""Set the name."""
self
.
_name
=
name
name
=
property
(
_GetName
,
_SetName
,
...
...
@@ -663,6 +692,9 @@ class CronLineTimeAction(object):
self
.
user
=
user
self
.
command
=
command
def
_CheckTimeField
(
self
,
log
):
pass
def
ValidateAndLog
(
self
,
log
):
"""Validates an @ time spec line and logs any errors and warnings.
...
...
@@ -675,7 +707,8 @@ class CronLineTimeAction(object):
if
self
.
user
in
USER_WHITELIST
:
return
elif
len
(
self
.
user
)
>
31
:
log
.
LineError
(
log
.
MSG_INVALID_USER
,
'Username too long "%s"'
%
self
.
user
)
log
.
LineError
(
log
.
MSG_INVALID_USER
,
'Username too long "%s"'
%
self
.
user
)
elif
self
.
user
.
startswith
(
'-'
):
log
.
LineError
(
log
.
MSG_INVALID_USER
,
'Invalid username "%s"'
%
self
.
user
)
elif
re
.
search
(
r
'[\s!"#$%&\'()*+,/:;<=>?@[\\\]^`{|}~]'
,
self
.
user
):
...
...
@@ -811,6 +844,7 @@ class CronLineFactory(object):
class
LogMsgKindNotFound
(
Exception
):
"""Exception for broken log messages."""
pass
...
...
setup.py
View file @
66955b6f
...
...
@@ -64,9 +64,9 @@ class CleanCmd(Command):
def
run
(
self
):
# Configure for this project.
suffixes2del
=
[
'MANIFEST'
,
'.pyc'
,
'chkcrontabc'
]
dirs2del
=
[
'./build'
,
'./dist'
]
dirs2ign
=
[
'./.git'
]
suffixes2del
=
[
'MANIFEST'
,
'.pyc'
,
'chkcrontabc'
]
dirs2del
=
[
'./build'
,
'./dist'
,
'./.tox'
,
'./.coverage'
]
dirs2ign
=
[
'./.git'
]
# End config.
doomed
=
set
()
# Change to base dir.
...
...
@@ -162,7 +162,7 @@ if 'setuptools' not in dir():
setup
(
cmdclass
=
cmdclass
,
name
=
'chkcrontab'
,
version
=
'1.
3
'
,
version
=
'1.
4a
'
,
url
=
'http://code.google.com/p/chkcrontab'
,
author
=
'Kevin Lyda'
,
author_email
=
'lyda@google.com'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment