Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.5 release #727

Merged
merged 27 commits into from
Feb 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4f54fdc
Prepare fore v1.5.0 release
bennuttall Feb 1, 2019
3685ffb
Huge docs tidy-up
waveform80 Feb 2, 2019
2d103eb
Code tidy up
waveform80 Feb 2, 2019
5a6411d
Fix #721
waveform80 Feb 2, 2019
32f216b
Fix pinout execution test
waveform80 Feb 2, 2019
f38436a
Generate device graphs automatically
waveform80 Feb 3, 2019
a2ebfef
Fix up the class hierarchy docs
waveform80 Feb 3, 2019
c3446e8
More class chart tidying
waveform80 Feb 3, 2019
db3c373
Add zip_values function to tools module (and update docs to use it)
bennuttall Feb 3, 2019
1f5614f
Add zip_values tests and fix broken examples
bennuttall Feb 4, 2019
eb190a0
Pass in mock_factory to zip_values test
bennuttall Feb 4, 2019
6b084c6
Remove unnecessary tests and remove unnecessary sleeps
bennuttall Feb 4, 2019
c1b8944
Add note about pigpio to TonalBuzzer
bennuttall Feb 4, 2019
cc3df8d
Add Philippe Muller to contributors and tidy up links in readme
bennuttall Feb 4, 2019
470e9f3
Update changelog
bennuttall Feb 4, 2019
f643840
Merge branch 'master' into docs-tidy-up
bennuttall Feb 7, 2019
c8b85dd
Fix Claire
bennuttall Feb 7, 2019
0193343
Simplify pin factories OrderedDict
bennuttall Feb 9, 2019
5248de1
Minor fixes to TonalBuzzer docs
waveform80 Feb 2, 2019
ddb272a
Sort output of class_graph
waveform80 Feb 9, 2019
8d4f2a6
Regenerate images
waveform80 Feb 9, 2019
fd65fdb
Correct the copyright to be consistent
waveform80 Feb 6, 2019
7326452
Create copyright generator
waveform80 Feb 6, 2019
1e07bb3
Update the MANIFEST
waveform80 Feb 9, 2019
3092239
Don't tar up .tox in the deb source!
waveform80 Feb 9, 2019
6f45c90
Generate license headers
waveform80 Feb 9, 2019
5f6add4
Update pinout to handle inability to construct pin factory
waveform80 Feb 10, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 8 additions & 10 deletions LICENCE.txt → LICENSE.rst
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
Copyright 2015- Raspberry Pi Foundation

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
* Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
include README.rst
recursive-include tests *.py
include LICENCE.txt
include LICENCE.rst
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ $(DIST_DSC): $(PY_SOURCES) $(SUBDIRS) $(DEB_SOURCES)
mkdir -p dist/
for f in $(DIST_DSC); do cp ../$${f##*/} dist/; done

copyrights: $(PY_SOURCES) $(DOC_SOURCES)
./copyrights

changelog: $(PY_SOURCES) $(DOC_SOURCES) $(DEB_SOURCES)
$(MAKE) clean
# ensure there are no current uncommitted changes
Expand Down
25 changes: 16 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ A simple interface to GPIO devices with Raspberry Pi.
Created by `Ben Nuttall`_ of the `Raspberry Pi Foundation`_, `Dave Jones`_, and
other contributors.

.. _Ben Nuttall: https://github.com/bennuttall
.. _Raspberry Pi Foundation: https://www.raspberrypi.org/
.. _Dave Jones: https://github.com/waveform80

About
=====

Expand Down Expand Up @@ -59,20 +63,28 @@ some more complex things like sensors, analogue-to-digital converters, full
colour LEDs, robotics kits and more. See the `Recipes`_ chapter of the
documentation for ideas on how to get started.

.. _Recipes: https://gpiozero.readthedocs.io/en/stable/recipes.html

Installation
============

GPIO Zero is installed by default in the Raspbian desktop image, available from
`raspberrypi.org`_. To install on Raspbian Lite or other operating systems,
including for PCs using remote GPIO, see the `Installing`_ chapter.

.. _raspberrypi.org: https://www.raspberrypi.org/downloads/
.. _Installing: https://gpiozero.readthedocs.io/en/stable/installing.html

Documentation
=============

Comprehensive documentation is available at https://gpiozero.readthedocs.io/.
Please refer to the `Contributing`_ and `Development`_ chapters in the
documentation for information on contributing to the project.

.. _Contributing: https://gpiozero.readthedocs.io/en/stable/contributing.html
.. _Development: https://gpiozero.readthedocs.io/en/stable/development.html

Contributors
============

Expand Down Expand Up @@ -103,17 +115,10 @@ Other contributors:
- `Fatih Sarhan`_
- `Rick Ansell`_
- `Jeevan M R`_
- `Claire Pollard`_
- `Philippe Muller`_


.. _Raspberry Pi Foundation: https://www.raspberrypi.org/
.. _raspberrypi.org: https://www.raspberrypi.org/downloads/
.. _Recipes: https://gpiozero.readthedocs.io/en/stable/recipes.html
.. _Contributing: https://gpiozero.readthedocs.io/en/stable/contributing.html
.. _Development: https://gpiozero.readthedocs.io/en/stable/development.html
.. _Installing: https://gpiozero.readthedocs.io/en/stable/installing.html

.. _Ben Nuttall: https://github.com/bennuttall
.. _Dave Jones: https://github.com/waveform80
.. _Andrew Scheller: https://github.com/lurch
.. _Martin O'Hanlon: https://github.com/martinohanlon
.. _Steve Amor: https://github.com/SteveAmor
Expand All @@ -134,3 +139,5 @@ Other contributors:
.. _Fatih Sarhan: https://github.com/f9n
.. _Rick Ansell: https://github.com/ricksbt
.. _Jeevan M R: https://github.com/jee1mr
.. _Claire Pollard: https://github.com/tuftii
.. _Philippe Muller: https://github.com/pmuller
208 changes: 208 additions & 0 deletions copyrights
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#!/usr/bin/env python

import io
import re
import sys
from collections import namedtuple
from operator import attrgetter
from itertools import groupby
from datetime import datetime
from subprocess import Popen, PIPE, DEVNULL
from pathlib import Path
from fnmatch import fnmatch
from functools import lru_cache


Contribution = namedtuple('Contribution', ('author', 'email', 'year', 'filename'))
Copyright = namedtuple('Copyright', ('author', 'email', 'years'))


def main():
includes = {
'**/*.py',
'**/*.rst',
}
excludes = {
'docs/examples/*.py',
'docs/license.rst',
}
prefixes = {
'.py': '#',
'.rst': '..',
}
if len(sys.argv) > 1:
includes = set(sys.argv[1:])
contributions = get_contributions(includes, excludes)
for filename, copyrights in contributions.items():
filename = Path(filename)
update_copyright(filename, copyrights, prefixes[filename.suffix])


def get_contributions(include, exclude):
sorted_blame = sorted(
get_blame(include, exclude),
key=lambda c: (c.filename, c.author, c.email)
)
blame_by_file = {
filename: list(file_contributions)
for filename, file_contributions in groupby(
sorted_blame, key=attrgetter('filename')
)
}
contributors_all_years = {
filename: {
Copyright(author, email, frozenset(y.year for y in years))
for (author, email), years in groupby(
file_contributors, key=lambda c: (c.author, c.email)
)
}
for filename, file_contributors in blame_by_file.items()
}
contributions = {
filename: {
Copyright(
c.author, c.email,
(min(c.years), max(c.years))
if len(c.years) > 1 else
min(c.years)
)
for c in contributors
}
for filename, contributors in contributors_all_years.items()
}
return contributions


def get_blame(include, exclude):
for filename in get_source_files(include, exclude):
blame = Popen(
['git', 'blame', '--line-porcelain', 'HEAD', '--', filename],
stdout=PIPE,
stderr=PIPE,
universal_newlines=True
)
author = email = year = None
for line in blame.stdout:
if line.startswith('author '):
author = line.split(' ', 1)[1].rstrip()
elif line.startswith('author-mail '):
email = line.split(' ', 1)[1].rstrip().lstrip('<').rstrip('>')
elif line.startswith('author-time '):
# Forget the timezone; we only want the year anyway
year = datetime.fromtimestamp(int(line.split(' ', 1)[1].rstrip())).year
elif line.startswith('filename '):
yield Contribution(
author=author, email=email, year=year, filename=filename)
author = email = year = None
blame.wait()
assert blame.returncode == 0


def get_source_files(include, exclude):
ls_tree = Popen(
['git', 'ls-tree', '-r', '--name-only', 'HEAD'],
stdout=PIPE,
stderr=DEVNULL,
universal_newlines=True
)
if not include:
include = {'*'}
for filename in ls_tree.stdout:
filename = filename.strip()
if any(fnmatch(filename, pattern) for pattern in exclude):
continue
if any(fnmatch(filename, pattern) for pattern in include):
yield filename
ls_tree.wait()
assert ls_tree.returncode == 0


insertion_point = object()
def parse_source_file(filename, prefix):
license = get_license()
license_start = license[0]
license_end = license[-1]
with filename.open('r') as source:
state = 'preamble'
for linenum, line in enumerate(source, start=1):
if state == 'preamble':
if linenum == 1 and line.startswith('#!'):
yield line
elif linenum < 10 and 'set fileencoding' in line:
yield line
elif line.rstrip() == prefix:
pass # skip blank comment lines
elif line.startswith(prefix + ' GPIO Zero:'):
pass # skip existing header lines
elif line.startswith(prefix + ' Copyright (c)'):
pass # skip existing copyright lines
elif line.startswith(prefix + ' ' + license_start):
state = 'license' # skip existing license lines
else:
yield insertion_point
state = 'blank'
elif state == 'license':
if line.startswith(prefix + ' ' + license_end):
yield insertion_point
state = 'blank'
continue
if state == 'blank':
# Ensure there's a blank line between license and start of the
# source body
if line.strip():
yield '\n'
yield line
state = 'body'
elif state == 'body':
yield line


def update_copyright(filename, copyrights, prefix):
print('Re-writing {filename}...'.format(filename=filename))
license = get_license()
copyrights = sorted(
copyrights, reverse=True, key=lambda c:
(c.years[::-1] if isinstance(c.years, tuple) else (c.years, 0), c.author)
)
content = []
for line in parse_source_file(filename, prefix):
if line is insertion_point:
if len(content) > 0:
content.append(prefix + '\n')
content.append(
prefix + " GPIO Zero: a library for controlling the "
"Raspberry Pi's GPIO pins\n")
for copyright in copyrights:
try:
start, end = copyright.years
except TypeError:
years = str(copyright.years)
else:
years = '{start}-{end}'.format(start=start, end=end)
content.append(
prefix + " Copyright (c) {years} "
"{copyright.author} <{copyright.email}>\n"
"".format(years=years, copyright=copyright))
content.append(prefix + '\n')
content.extend(
(prefix + ' ' + l).strip() + '\n'
for l in license
)
else:
content.append(line)
# Yes, if I was doing this "properly" I'd write to a temporary file and
# rename it over the target. However, I'm assuming you're running this
# under a git clone ... after all, you are ... aren't you?
with filename.open('w') as target:
for line in content:
target.write(line)


@lru_cache()
def get_license():
with io.open('LICENSE.rst', 'r') as text:
return text.read().splitlines()


if __name__ == '__main__':
main()
1 change: 1 addition & 0 deletions debian/docs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
README.rst
LICENSE.rst
9 changes: 6 additions & 3 deletions debian/source/options
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
diff-ignore
tar-ignore
tar-ignore = dist
tar-ignore = docs/_build
tar-ignore = .cache
tar-ignore = .coverage
tar-ignore = tags
tar-ignore = *.egg-info
tar-ignore = .cache
tar-ignore = .pytest_cache
tar-ignore = .coverage*
tar-ignore = .github
tar-ignore = .tox
tar-ignore = *.fzz
tar-ignore = *.xcf
34 changes: 34 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = ../build
PY_SOURCES := $(wildcard ../gpiozero/*.py ../gpiozero/pins/*.py)
DOT_DIAGRAMS := $(wildcard images/*.dot)
MSC_DIAGRAMS := $(wildcard images/*.mscgen)
GPI_DIAGRAMS := $(wildcard images/*.gpi)
Expand Down Expand Up @@ -180,6 +181,39 @@ pseudoxml:
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

images/device_hierarchy.dot: $(PY_SOURCES)
./images/class_graph \
-i Device \
-i SharedMixin \
-x SPI -x SPISoftwareBus > $@

images/composite_device_hierarchy.dot: $(PY_SOURCES)
./images/class_graph \
-i CompositeDevice \
-i Energenie \
-i LedBord \
-x Motor \
-x PhaseEnableMotor \
-x Servo \
-o SourceMixin -o HoldMixin > $@

images/spi_device_hierarchy.dot: $(PY_SOURCES)
./images/class_graph -i SPIDevice > $@

images/output_device_hierarchy.dot: $(PY_SOURCES)
./images/class_graph \
-i OutputDevice \
-i RGBLED \
-i Servo \
-i Motor \
-i PhaseEnableMotor \
-i TonalBuzzer \
-x LedBorg \
-x SPI -o SourceMixin > $@

images/input_device_hierarchy.dot: $(PY_SOURCES)
./images/class_graph -i InputDevice -o EventsMixin -o HoldMixin > $@

%.svg: %.mscgen
mscgen -T svg -o $@ $<

Expand Down