Skip to content

Commit 2fab74a

Browse files
committed
Functional updates to add line function support. Bumped version and updated docs.
1 parent e8edc42 commit 2fab74a

File tree

7 files changed

+116
-32
lines changed

7 files changed

+116
-32
lines changed

CHANGELOG.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
= Verace Changelog
22

3+
== verace-0.4.0 (2018-01-15)
4+
=== Release highlights
5+
- Non-breaking functional updates.
6+
7+
=== All additions and changes
8+
- Added support for line functions.
9+
10+
=== Bug fixes
11+
- Minor fix for functions that return no `VerInfo`.
12+
313
== verace-0.3.2 (2018-01-14)
414
=== Release highlights
515
- Minor tweaks.

README.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Get the string found by the checker:
4949
[source,python]
5050
--------
5151
print("version found = " + mychk.string())
52-
# version found = 0.3.2
52+
# version found = 0.4.0
5353
--------
5454

5555
The string can be updated in all associated files:

doc/source/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@
5353
# built documents.
5454
#
5555
# The short X.Y version.
56-
version = u'0.3.2'
56+
version = u'0.4.0'
5757
# The full version, including alpha/beta/rc tags.
58-
release = u'0.3.2'
58+
release = u'0.4.0'
5959

6060
# The language for content autogenerated by Sphinx. Refer to documentation
6161
# for a list of supported languages.

doc/source/index.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,24 @@ This class is used to create objects that will check/update strings in files:
1818

1919
Custom Check Functions
2020
----------------------
21-
A function can be provided to ``VerChecker.include()``. If no explicit function is provide, the following function will be used:
21+
A function can be provided to ``VerChecker.include()``. The function will be used to parse the file for the target string.
22+
23+
If a tuple/list is provided as as the ``func`` argument, the first value must be a function and the second value must be the string ``'file'`` (default) or ``'line'``.
24+
25+
If no explicit function is provide, the following file function will be used:
2226

2327
.. autofunction:: verace.check_basic
2428

25-
Custom functions can be defined to find strings. The first argument must be the file path and the function must return either a single ``VerInfo`` object or a list of ``VerInfo`` objects:
29+
File Functions
30+
~~~~~~~~~~~~~~
31+
File functions must handle the string search through the entire target file. The first argument must be the file path and the function must return either a single ``VerInfo`` object or a list of ``VerInfo`` objects:
2632

2733
.. autodata:: verace.VerInfo
2834

2935
Use this convenience function to iterate through the lines in a given file:
3036

3137
.. autofunction:: verace.readlines
38+
39+
Line Functions
40+
~~~~~~~~~~~~~~
41+
Line functions will be provided each line from the file one at a time. If the target string is found, simply return it. Otherwise return None (default return).

lib/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
setup(
55
name = "verace",
6-
version = "0.3.2",
6+
version = "0.4.0",
77
author = "Jeff Rimko",
88
author_email = "jeffrimko@gmail.com",
99
description = "Library for checking version strings in project files.",

lib/verace.py

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
##==============================================================#
2222

2323
#: Library version string.
24-
__version__ = "0.3.2"
24+
__version__ = "0.4.0"
2525

2626
#: Contains information for a single checked item.
2727
VerInfo = namedtuple("VerInfo", "path linenum string")
@@ -48,6 +48,42 @@ def __init__(self, name, root):
4848
self._string = None
4949
self._checks = []
5050
self.debug = False
51+
def _run_check(self, c):
52+
"""Runs a single VerCheck and returns a list of (VerInfo,updatable)
53+
tuples."""
54+
dprint = get_vprint(self.debug)
55+
# Setup file path.
56+
path = c.path
57+
if not op.isabs(path):
58+
path = op.join(self.root, path)
59+
path = op.normpath(path)
60+
# Setup function and function type.
61+
if type(c.func) in [list, tuple]: func,ftyp = c.func
62+
else: func,ftyp = (c.func, "file")
63+
if (not func) or (not hasattr(func, "__call__")):
64+
func = check_basic
65+
# Run the function over the file and collect VerInfo objects.
66+
vinfos = []
67+
if "file" == ftyp:
68+
v = func(path, **c.opts)
69+
dprint((inspect.stack()[0][3], c, v))
70+
if list != type(v): v = [v]
71+
vinfos += v
72+
elif "line" == ftyp:
73+
for num,line in readlines(path):
74+
string = func(line, **c.opts)
75+
if string:
76+
vinfos.append(VerInfo(path, num, string))
77+
return [(v, c.updatable) for v in vinfos if v]
78+
def _iter_vinfo(self, get_updatable=False):
79+
"""Iterates over the associated VerInfo objects. Optionally returns if
80+
the associated file is updatable."""
81+
vlist = [] # Holds (VerInfo,updatable) items.
82+
for c in self._checks:
83+
vlist += self._run_check(c)
84+
for vu in sorted(vlist, key=lambda i: (i[0].path, i[0].linenum)):
85+
if vu:
86+
yield vu if get_updatable else vu[0]
5187
def string(self):
5288
"""Returns the string if `run()` found no inconsistencies,
5389
otherwise None is returned. Always calls `run()`."""
@@ -58,45 +94,28 @@ def include(self, path, func=None, opts=None, updatable=True, **kwargs):
5894
5995
**Params**:
6096
- path (str) - Path to a file to check.
61-
- func (function) - Function that performs check will be passed
62-
`path` and `opts`. Must return a VerInfo (single or list).
97+
- func (function|(tuple,str)) - Either a (func,type) tuple or a
98+
function (type defaults to 'file'). Valid type values are
99+
'file|line'. The type controls whether the file path or individual
100+
lines will be passed to the function. A file function may return
101+
either single VerInfo or a list of VerInfos. A line function may
102+
return a string.
63103
- opts (dict) - Options to pass to the check function. Any additional
64104
keyword args will be included.
65105
- updatable (bool) - If true, string can be updated using `update()`.
66106
"""
67107
if not opts:
68108
opts = {}
69109
opts.update(copy.deepcopy(kwargs))
70-
if (not func) or (not hasattr(func, "__call__")):
71-
func = check_basic
72110
c = VerCheck(path, func, copy.deepcopy(opts), updatable)
73111
self._checks.append(c)
74-
def iter_vinfo(self, get_updatable=False):
75-
"""Iterates over the associated VerInfo objects. Optionally returns if
76-
the associated file is updatable."""
77-
dprint = get_vprint(self.debug)
78-
vlist = [] # Holds (vinfo,updatable) items.
79-
for c in self._checks:
80-
path = c.path
81-
if not op.isabs(path):
82-
path = op.join(self.root, path)
83-
path = op.normpath(path)
84-
vinfos = c.func(path, **c.opts)
85-
dprint((inspect.stack()[0][3], c, vinfos))
86-
if list != type(vinfos):
87-
vinfos = [vinfos]
88-
for v in vinfos:
89-
vlist.append((v,c.updatable))
90-
for vu in sorted(vlist, key=lambda i: (i[0].path, i[0].linenum)):
91-
if vu:
92-
yield vu if get_updatable else vu[0]
93112
def run(self, verbose=True):
94113
"""Runs checks on all included items, reports any inconsistencies.
95114
Returns string if consistent else None."""
96115
vprint = get_vprint(verbose)
97116
strings = []
98117
vprint(self.name + ":")
99-
for vinfo in self.iter_vinfo():
118+
for vinfo in self._iter_vinfo():
100119
if vinfo.string not in strings:
101120
strings.append(vinfo.string)
102121
vprint(" `%s` (%s:%u)" % (
@@ -116,7 +135,7 @@ def update(self, newstr):
116135
caution as this will modify file content! Returns number of strings
117136
updated."""
118137
updated = 0
119-
for vinfo,updatable in self.iter_vinfo(get_updatable=True):
138+
for vinfo,updatable in self._iter_vinfo(get_updatable=True):
120139
if not updatable:
121140
continue
122141
with open(vinfo.path) as fi:

tests/linefunc_test_1.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""Tests the basic usage of VerChecker."""
2+
3+
##==============================================================#
4+
## SECTION: Imports #
5+
##==============================================================#
6+
7+
from testlib import *
8+
9+
from verace import VerChecker
10+
11+
##==============================================================#
12+
## SECTION: Class Definitions #
13+
##==============================================================#
14+
15+
class TestCase(unittest.TestCase):
16+
17+
def setUp(test):
18+
test.verchk = VerChecker("Basic Version", __file__)
19+
20+
def test_version(test):
21+
def getver(line):
22+
if "version =" in line:
23+
return line.split('"')[1]
24+
test.verchk.include("checkfiles/multi.txt", func=(getver, "line"))
25+
test.assertEqual(test.verchk.string(), "1.2.3")
26+
27+
def test_different(test):
28+
def getdiff(line):
29+
if "different =" in line:
30+
return line.split('"')[1].split(",")[0]
31+
test.verchk.include("checkfiles/multi.txt", func=(getdiff, "line"))
32+
test.assertEqual(test.verchk.string(), "0.0.0")
33+
34+
def test_none(test):
35+
def getnone(line):
36+
return
37+
test.verchk.include("checkfiles/multi.txt", func=(getnone, "line"))
38+
test.assertEqual(test.verchk.string(), None)
39+
40+
##==============================================================#
41+
## SECTION: Main Body #
42+
##==============================================================#
43+
44+
if __name__ == '__main__':
45+
unittest.main()

0 commit comments

Comments
 (0)