Nosy for hardware CI
The problem
Recently I sent to the pcb manufacturer a zip file that didn't contain the latest Gerber/Drill file set. During the smd-assembly set-up it was discovered that the BOM had 2 smd fuses that did not exist to the pcb The zip was created at 14:00 while the latest Gerber files at 16:00 Since I was aplying version control with TortoiseHg, I was able to understand the state of the design at 14:00. I was lucky that the PCB was ok to assemble, only 2 smd fuses for the USB supply was missing. That was my final update for the pcb-design. So the question arised: How to avoid the same problem in the next projects. I needed a Continous Integration tool, simple and easy to run inside my development (windows)pc. Nosy is a python tool, so I started installation and evaluation. With some minor modifications it worked, so now I can (re)organize my pcb-design workflow having more consistent deliverables in an automatic way.
Official version
- This is much more functional than the simple version below which was tested initially, since the setup.cfg file is flexible and provides global behavior change if placed in the PATH. I have changed the behavior, since I didn't want to call nose, but a DOS .cmd file to create a zip file whenever the set of Gerber files is changed. This way Continous Integration is applied to my hardware design pcb-manufacturing-deliverable(s) zip
- https://pypi.python.org/pypi/nosy
install by:
python setup.py install
then at installed directory:
C:\Python27\nosy-1.1.2\nosy
edit nosy.py at line 148:
subprocess.call('fab.cmd')
to call instead of nose, our 'stuff', in this test fab.cmd was called, then reinstall:
python setup.py install
misc
- https://nose.readthedocs.org/en/latest/
- http://douglatornell.ca/software/python/Nosy/
- https://coderwall.com/p/tkzuew
- https://coderwall.com/p/nikegg
GitHub
nikoschalikias Oct2013
Simple version
tested
Nikos version as below: <python>
- !/usr/bin/env python
- nosy: commandline continuous integration for test driven development
- Copyright (C) 2008 Michael Steder <steder@gmail.com>
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
""" Nosy - Script to monitor changes to *.py files and rerun tests
NOTE: Credit for the idea goes to Jeff Wrinkler. Today there are other versions of this on PyPI (one called nosy and another called nosyd) but I didn't like the config file required in both cases.
What makes this version different, and better IMHO, is that Nosy simply acts as a passthrough to the underlying commandline test runner. You don't have to learn how to use a new test tool and create a config file you just replace the normal commandline with nosy and get on with your life.
So if you normally run nosetests like this::
$ nosetests --nocapture --with-coverage --cover-package=<mypackage> mypackage
You can simply run nosy instead of nosetests like this to have your tests rerun whenever the code changes::
$ nosy --nocapture --with-coverage --cover-package=<mypackage> mypackage
Nosy currenly walks the working directory for *.py files and only re-runs when *.py files change.
TODO:
- integrate building documentation - run syntax checker (pyflakes / pylint) - rename and publish on pypi?
"""
""" Nikos 24/10/2014: DONE: TEST_RUNNER changed to the dos-command file to run, PATTERNS changed from *.py to *.* TODO: To be able to run to specified subdirectory """
__version__ = 1.0
import fnmatch import os import subprocess import stat import sys import time
TEST_RUNNER = "fab.cmd" PATTERNS = ["*.*",]
def checksum_directory(directory):
""" Walk directory structure and return simple checksum based on file size and modified time.
""" file_checksums = [] for dirpath, dirnames, filenames in os.walk(directory, topdown=False, onerror=None, followlinks=False): source_names = [name for pattern in PATTERNS for name in filenames if fnmatch.fnmatch(name, pattern)] for source_name in source_names: source_path = os.path.join(dirpath, source_name) try: stats = os.stat(source_path) except OSError: # ignore temp files and files we don't # have perms to access continue file_checksums.append( stats[stat.ST_SIZE] + stats[stat.ST_MTIME]) return sum(file_checksums)
def main():
args = " ".join(sys.argv[1:]) command = "%s %s"%(TEST_RUNNER, args)
latest_checksum = checksum_directory(os.curdir) print "Nosy starting with: %s"%(command) print command subprocess.call(command.split()) try: while (True): checksum = checksum_directory(os.curdir) if checksum != latest_checksum: print "Nosy detected a change and is rerunning tests with: %s"%(command) latest_checksum = checksum subprocess.call(command.split()) time.sleep(1) except KeyboardInterrupt: print "Exiting Nosy..."
if __name__=="__main__":
main()
</python>