Skip to content

Update coding standards #1267

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

Merged
merged 1 commit into from
Feb 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
674 changes: 0 additions & 674 deletions COPYING

This file was deleted.

File renamed without changes.
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,21 @@ Documentation can be found at <http://scitools.org.uk/cartopy/docs/latest/>.
- To chat with developers and other users you can use the
[Gitter Chat](https://gitter.im/SciTools/cartopy)

## License and copyright

Cartopy is licensed under GNU Lesser General Public License (LGPLv3).
## Credits, copyright and license

Development occurs on GitHub at <https://github.com/SciTools/cartopy>, with a
contributor's license agreement (CLA) that can be found at
<http://scitools.org.uk/governance.html>.
Cartopy is developed collaboratively under the SciTools umberella.

(C) British Crown Copyright, Met Office
A full list of codecontributors ("Cartopy contributors") can be found at
https://github.com/SciTools/cartopy/graphs/contributors.

Code is just one of many ways of positively contributing to Cartopy, please see
our [contributing guide](.github/CONTRIBUTING.md) for more details on how
you can get involved.

Cartopy is released under a LGPL license with a shared copyright model.
See [LICENSE](LICENSE) for full terms.

The [Met Office](https://metoffice.gov.uk) has made a significant
contribution to the development, maintenance and support of this library.
All Met Office contributions are copyright on behalf of the British Crown.
18 changes: 3 additions & 15 deletions lib/cartopy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
# (C) British Crown Copyright 2011 - 2018, Met Office
# Copyright Cartopy Contributors
#
# This file is part of cartopy.
#
# cartopy is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# cartopy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with cartopy. If not, see <https://www.gnu.org/licenses/>.
# This file is part of Cartopy and is released under the LGPL license.
# See LICENSE in the root of the repository for full licensing details.

from __future__ import (absolute_import, division, print_function)

Expand Down
99 changes: 60 additions & 39 deletions lib/cartopy/tests/test_coding_standards.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
# (C) British Crown Copyright 2012 - 2018, Met Office
# Copyright Cartopy Contributors
#
# This file is part of cartopy.
#
# cartopy is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# cartopy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with cartopy. If not, see <https://www.gnu.org/licenses/>.
# This file is part of Cartopy and is released under the LGPL license.
# See LICENSE in the root of the repository for full licensing details.

from __future__ import (absolute_import, division, print_function)

Expand Down Expand Up @@ -51,8 +39,19 @@

LICENSE_RE_PATTERN = re.escape(LICENSE_TEMPLATE).replace(r'\{YEARS\}', '(.*?)')
# Add shebang possibility or C comment starter to the LICENSE_RE_PATTERN
LICENSE_RE_PATTERN = r'((\#\!.*|\/\*)\n)?' + LICENSE_RE_PATTERN
LICENSE_RE = re.compile(LICENSE_RE_PATTERN, re.MULTILINE)
SHEBANG_PATTERN = r'((\#\!.*|\/\*)\n)?'
LICENSE_RE = re.compile(SHEBANG_PATTERN + LICENSE_RE_PATTERN, re.MULTILINE)


LICENSE_TEMPLATE_v2 = """
# Copyright Cartopy Contributors
#
# This file is part of Cartopy and is released under the LGPL license.
# See LICENSE in the root of the repository for full licensing details.
""".strip()
LICENSE_RE_PATTERN_v2 = re.escape(LICENSE_TEMPLATE_v2)
LICENSE_RE_v2 = re.compile(SHEBANG_PATTERN + LICENSE_RE_PATTERN_v2,
re.MULTILINE)


# Guess cartopy repo directory of cartopy - realpath is used to mitigate
Expand All @@ -64,16 +63,16 @@

class TestLicenseHeaders(object):
@staticmethod
def years_of_license_in_file(fh):
def years_of_license_in_file(content, fname):
"""
Using :data:`LICENSE_RE` look for the years defined in the license
header of the given file handle.

If the license cannot be found in the given fh, None will be returned,
else a tuple of (start_year, end_year) will be returned.
If the license cannot be found in the given content, None will be
returned, else a tuple of (start_year, end_year) will be returned.

"""
license_matches = LICENSE_RE.match(fh.read())
license_matches = LICENSE_RE.match(content)
if not license_matches:
# no license found in file.
return None
Expand All @@ -84,7 +83,6 @@ def years_of_license_in_file(fh):
elif len(years) == 11:
start_year, end_year = int(years[:4]), int(years[7:])
else:
fname = getattr(fh, 'name', 'unknown filename')
raise ValueError("Unexpected year(s) string in {}'s copyright "
"notice: {!r}".format(fname, years))
return (start_year, end_year)
Expand Down Expand Up @@ -147,19 +145,35 @@ def test_license_headers(self):
if ext in ('.py', '.pyx', '.c', '.cpp', '.h') and \
os.path.isfile(full_fname) and \
not any(fnmatch(fname, pat) for pat in exclude_patterns):

is_empty = os.path.getsize(full_fname) == 0

with io.open(full_fname, encoding='utf-8') as fh:
years = TestLicenseHeaders.years_of_license_in_file(fh)
if years is None:
print('The file {} has no valid header license and '
'has not been excluded from the license header '
'test.'.format(fname))
failed = True
elif last_change.year > years[1]:
print('The file header at {} is out of date. The last'
' commit was in {}, but the copyright states it'
' was {}.'.format(fname, last_change.year,
years[1]))
failed = True
content = fh.read()

is_yearless_license = bool(LICENSE_RE_v2.match(content))
years = TestLicenseHeaders.years_of_license_in_file(
content, full_fname)

if is_empty:
# Allow completely empty files (e.g. ``__init__.py``)
pass
elif is_yearless_license:
# Allow new style license (v2).
pass

# What is left is the old-style (pre 2019) header.
elif years is None:
print('The file {} has no valid header license and '
'has not been excluded from the license header '
'test.'.format(fname))
failed = True
elif last_change.year > years[1]:
print('The file header at {} is out of date. The last'
' commit was in {}, but the copyright states it'
' was {}.'.format(fname, last_change.year,
years[1]))
failed = True

if failed:
raise ValueError('There were license header failures. See stdout.')
Expand Down Expand Up @@ -197,14 +211,21 @@ def test_future_imports(self):
if any(fnmatch(full_fname, pat) for pat in self.excluded):
continue

is_empty = os.path.getsize(full_fname) == 0

with io.open(full_fname, "r", encoding='utf-8') as fh:
content = fh.read()

if re.search(self.future_imports_pattern, content) is None:
print('The file {} has no valid __future__ imports '
'and has not been excluded from the imports '
'test.'.format(full_fname))
failed = True
has_future_import = re.search(
self.future_imports_pattern, content) is not None

if is_empty:
pass
elif not has_future_import:
print('The file {} has no valid __future__ imports '
'and has not been excluded from the imports '
'test.'.format(full_fname))
failed = True

if failed:
raise ValueError('There were __future__ import check failures. '
Expand Down