Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
89997dd
Refactor util tests and main code
pombredanne Nov 16, 2018
71ab957
Move class FakeResponse to test_api
pombredanne Nov 16, 2018
67926e6
Add new test to validate own ABOUT files
pombredanne Nov 16, 2018
c4cc41e
Streamline API call test and code
pombredanne Nov 16, 2018
9a45d28
Improve attribution template validation tests
pombredanne Nov 16, 2018
13f5fcd
Add FIXME comment
pombredanne Nov 16, 2018
a57cbaf
Add more tests for util. check_duplicate_keys_about_file
pombredanne Nov 16, 2018
3185c41
Streamline atrrib generation tests
pombredanne Nov 16, 2018
e2bf924
Add to_dict() function to Error object
pombredanne Nov 16, 2018
15957f5
Move deduplicate function to util.unique
pombredanne Nov 16, 2018
67a6e3e
Limit usage of posixpath to the minimum
pombredanne Nov 16, 2018
a6d8aec
Use util.unique for model
pombredanne Nov 16, 2018
c2689a3
Add TODO / FIXME comment as reminders
pombredanne Nov 16, 2018
d7be24b
Remove redundant u'' unicode string markers
pombredanne Nov 17, 2018
0cba7b8
Use util.unique and prefer os.path to posixpath
pombredanne Nov 17, 2018
8703949
Refine error report when validating own ABOUT
pombredanne Nov 17, 2018
851aa4f
Refactor util.inventory_filter function
pombredanne Nov 17, 2018
1c48705
Remove mapping_output feature
pombredanne Nov 17, 2018
2757387
Streamline command handlers
pombredanne Nov 17, 2018
6e16251
Stream line attribution generation code
pombredanne Nov 17, 2018
b47752d
Add test to load_csv with mapping
pombredanne Nov 17, 2018
7a1adb0
Add TODO comment
pombredanne Nov 17, 2018
ed9d226
Move test_gen test data to test_gen/ dir
pombredanne Nov 17, 2018
d497a4c
Use aboutcode-toolkit-extract- prefix for zip extraction dirs
pombredanne Nov 17, 2018
70d18ea
Do not use u'' unicode prefix
pombredanne Nov 17, 2018
091acd9
Add extra empty lines to separate code blocks
pombredanne Nov 17, 2018
173aeb1
Reorg tests and remove unused test files and code
pombredanne Nov 17, 2018
bdc74eb
Add new test to validate CLI help
pombredanne Nov 17, 2018
b2f5c41
Do not test import for coverage
pombredanne Nov 17, 2018
9e1f195
Revert to using AboutCommand for Click bug
pombredanne Nov 17, 2018
8d28cef
Run all tests on Travis CI, including doctests
pombredanne Nov 17, 2018
8e46b13
Use intermediate variable
pombredanne Nov 17, 2018
28cc7d0
Properly escape backslash
pombredanne Nov 17, 2018
b77b590
Make test work on Python3 and Windows
pombredanne Nov 17, 2018
e386049
Ignore pyenv .pyhon-version configuration file
pombredanne Nov 17, 2018
f881126
Load test files as Unicode
pombredanne Nov 17, 2018
462de79
Correct AboutCommand command subclass main call
pombredanne Nov 17, 2018
fd90791
Test sdtout text as lines list
pombredanne Nov 17, 2018
9dbf8ac
Use click to test TTY cli code
pombredanne Nov 17, 2018
c5ac448
Clarify use of \ backslashes in docstrings
pombredanne Nov 17, 2018
b956107
Add full command line tests
pombredanne Nov 17, 2018
d0e061e
Rename gen --license-notice-text-location #367
pombredanne Nov 18, 2018
dc439a3
Update CLI help and validation
pombredanne Nov 18, 2018
d23f4c3
Do not rename --vartext option yet #332
pombredanne Nov 18, 2018
b45ad61
Remove duplicated code in validators
pombredanne Nov 18, 2018
6d52e73
Remove unused arguments and file
pombredanne Nov 18, 2018
e230982
Add new CSV transform subcommand #361
pombredanne Nov 18, 2018
7bf44bd
Use new saneyaml library
pombredanne Nov 19, 2018
409e4b0
Use ordered mapping for consistent field order
pombredanne Nov 20, 2018
0d23465
Merge pull request #371 from nexB/saneyaml-library
pombredanne Nov 21, 2018
69f5dfa
Merge pull request #370 from nexB/361-csv-transform-subcommand
pombredanne Nov 21, 2018
1611573
Remove unused function
pombredanne Nov 21, 2018
e762df0
Fix help doc typo
pombredanne Nov 21, 2018
404b517
Ignore tox directory
pombredanne Nov 21, 2018
45696f1
Import csv / backports.csv from util module only
pombredanne Nov 21, 2018
54e5265
Monkey patch csv and remove unused code
pombredanne Nov 21, 2018
2767988
Remove unused code
pombredanne Nov 21, 2018
85c1c18
Use proper paths for test files
pombredanne Nov 21, 2018
b3ed23f
Add tox file for local testing
pombredanne Nov 21, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@ docs/_build
/.cache/
/.settings/
/tcl/
/.python-version
/.tox/
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ install:
- ./configure etc/conf/dev

script:
- bin/py.test -vvs tests
- bin/py.test -vvs

notifications:
irc:
Expand Down
35 changes: 0 additions & 35 deletions about.cfg

This file was deleted.

3 changes: 2 additions & 1 deletion etc/scripts/irc-notify.py.ABOUT
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
about_resource: irc-notify.py
name: irc-notify.py
version: def54f8166089b733d166665fdabcad4cdc526d8
download_url: https://raw.githubusercontent.com/gridsync/gridsync/def54f8166089b733d166665fdabcad4cdc526d8/misc/irc-notify.py
description: Quick and dirty IRC notification script.
homepage_url: https://github.com/gridsync/gridsync
owner: Christopher R. Wood
copyright: Copyright (C) 2015-2016 Christopher R. Wood
dje_license_key: gpl-2.0-plus
license_expression: gpl-2.0-plus
license_text_file: gpl-2.0.LICENSE
notice_text: |
This program is free software; you can redistribute it and/or modify it under the
Expand Down
11 changes: 5 additions & 6 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,23 @@ release = clean --all sdist --formats=bztar,zip bdist_wheel
[tool:pytest]
norecursedirs =
.git
.cache
.settings
bin
dist
dist
build
_build
dist
local
ci
docs
man
share
samples
.cache
.settings
example
etc
Include
include
Lib
lib
local
Scripts
thirdparty
tmp
Expand Down
10 changes: 8 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,15 @@ def read(*names, **kwargs):
],
install_requires=[
'jinja2 >= 2.9, < 3.0',

'click >= 6.7, < 7.0',

"backports.csv ; python_version<'3.6'",
'PyYAML >= 3.0, < 4.0',

# required by saneyaml
'PyYAML >= 3.11, <=3.13',
'saneyaml',

'boolean.py >= 3.5, < 4.0',
'license_expression >= 0.94, < 1.0',
],
Expand All @@ -79,7 +85,7 @@ def read(*names, **kwargs):
},
entry_points={
'console_scripts': [
'about=attributecode.cmd:cli',
'about=attributecode.cmd:about',
]
},
)
80 changes: 47 additions & 33 deletions src/attributecode/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@

from collections import namedtuple
import logging
import os

try:
unicode # Python 2
except NameError:
unicode = str # Python 3 #NOQA
# Python 2
unicode # NOQA
except NameError: # pragma: nocover
# Python 3
unicode = str # NOQA

import saneyaml

__version__ = '3.3.0'


__about_spec_version__ = '3.1'

__copyright__ = """
Expand All @@ -53,39 +56,46 @@ class Error(namedtuple('Error', ['severity', 'message'])):
def __new__(self, severity, message):
if message:
if isinstance(message, unicode):
message = clean_string(message)
message = self._clean_string(message)
else:
message = clean_string(unicode(repr(message), encoding='utf-8'))
message = self._clean_string(unicode(repr(message), encoding='utf-8'))
message = message.strip('"')

return super(Error, self).__new__(
Error, severity, message)

def __repr__(self, *args, **kwargs):
sev = severities[self.severity]
msg = clean_string(repr(self.message))
msg = self._clean_string(repr(self.message))
return 'Error(%(sev)s, %(msg)s)' % locals()


def clean_string(s):
"""
Return a cleaned string for `s`, stripping eventual "u" prefixes
from unicode representations.
"""
if not s:
def to_dict(self, *args, **kwargs):
"""
Return an ordered mapping of self.
"""
return self._asdict()

@staticmethod
def _clean_string(s):
"""
Return a cleaned string for `s`, stripping eventual "u" prefixes
from unicode representations.
"""
if not s:
return s
if s.startswith(('u"', "u'")):
s = s.lstrip('u')
s = s.replace('[u"', '["')
s = s.replace("[u'", "['")
s = s.replace("(u'", "('")
s = s.replace("(u'", "('")
s = s.replace("{u'", "{'")
s = s.replace("{u'", "{'")
s = s.replace(" u'", " '")
s = s.replace(" u'", " '")
s = s.replace("\\\\", "\\")
return s
if s.startswith(('u"', "u'")):
s = s.lstrip('u')
s = s.replace('[u"', '["')
s = s.replace("[u'", "['")
s = s.replace("(u'", "('")
s = s.replace("(u'", "('")
s = s.replace("{u'", "{'")
s = s.replace("{u'", "{'")
s = s.replace(" u'", " '")
s = s.replace(" u'", " '")
s = s.replace("\\\\", "\\")
return s


# modeled after the logging levels
CRITICAL = 50
Expand All @@ -97,10 +107,14 @@ def clean_string(s):


severities = {
CRITICAL : u'CRITICAL',
ERROR : u'ERROR',
WARNING : u'WARNING',
INFO : u'INFO',
DEBUG : u'DEBUG',
NOTSET : u'NOTSET'
}
CRITICAL : 'CRITICAL',
ERROR : 'ERROR',
WARNING : 'WARNING',
INFO : 'INFO',
DEBUG : 'DEBUG',
NOTSET : 'NOTSET'
}


DEFAULT_MAPPING = os.path.join(os.path.abspath(
os.path.dirname(__file__)), 'mapping.config')
2 changes: 1 addition & 1 deletion src/attributecode/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
from __future__ import unicode_literals


if __name__ == '__main__':
if __name__ == '__main__': # pragma: nocover
from attributecode import cmd
cmd.cli()
59 changes: 39 additions & 20 deletions src/attributecode/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,35 @@

import json

try: # Python 2
from urllib import urlencode, quote
from urllib2 import urlopen, Request, HTTPError
except ImportError: # Python 3
from urllib.parse import urlencode, quote
from urllib.request import urlopen, Request
from urllib.error import HTTPError

from attributecode import ERROR
from attributecode import Error
from attributecode.util import python2


if python2: # pragma: nocover
from urllib import quote # NOQA
from urllib import urlencode # NOQA
from urllib2 import HTTPError # NOQA
from urllib2 import Request # NOQA
from urllib2 import urlopen # NOQA
else: # pragma: nocover
from urllib.parse import quote # NOQA
from urllib.parse import urlencode # NOQA
from urllib.request import Request # NOQA
from urllib.request import urlopen # NOQA
from urllib.error import HTTPError # NOQA


"""
API call helpers
"""


def request_license_data(url, api_key, license_key):
# FIXME: args should start with license_key
def request_license_data(api_url, api_key, license_key):
"""
Return a dictionary of license data.
Send a request to a given API URL to gather license data for
license_key, authenticating through an api_key.
Return a tuple of (dictionary of license data, list of errors) given a
`license_key`. Send a request to `api_url` authenticating with `api_key`.
"""
headers = {
'Authorization': 'Token %s' % api_key,
Expand All @@ -52,9 +59,10 @@ def request_license_data(url, api_key, license_key):
'format': 'json'
}

url = url.rstrip('/')
encoded_payload = urlencode(payload)
full_url = '%(url)s/?%(encoded_payload)s' % locals()
api_url = api_url.rstrip('/')
payload = urlencode(payload)

full_url = '%(api_url)s/?%(payload)s' % locals()
# handle special characters in URL such as space etc.
quoted_url = quote(full_url, safe="%/:=&?~#+!$,;'@()*[]")

Expand All @@ -64,10 +72,12 @@ def request_license_data(url, api_key, license_key):
request = Request(quoted_url, headers=headers)
response = urlopen(request)
response_content = response.read().decode('utf-8')
# FIXME: this should be an ordered dict
license_data = json.loads(response_content)
if not license_data['results']:
msg = u"Invalid 'license': %s" % license_key
errors.append(Error(ERROR, msg))

except HTTPError as http_e:
# some auth problem
if http_e.code == 403:
Expand All @@ -80,20 +90,29 @@ def request_license_data(url, api_key, license_key):
# this exception.
msg = u"Invalid 'license': %s" % license_key
errors.append(Error(ERROR, msg))

except Exception as e:
errors.append(Error(ERROR, str(e)))

finally:
license_data = license_data.get('results')[0] if license_data.get('count') == 1 else {}
if license_data.get('count') == 1:
license_data = license_data.get('results')[0]
else:
license_data = {}

return license_data, errors


def get_license_details_from_api(url, api_key, license_key):
# FIXME: args should start with license_key
def get_license_details_from_api(api_url, api_key, license_key):
"""
Return the license_text of a given license_key using an API request.
Return an empty string if the text is not available.
Return a tuple of license data given a `license_key` using the `api_url`
authenticating with `api_key`.
The details are a tuple of (license_name, license_key, license_text, errors)
where errors is a list of strings.
Missing values are provided as empty strings.
"""
license_data, errors = request_license_data(url, api_key, license_key)
license_data, errors = request_license_data(api_url, api_key, license_key)
license_name = license_data.get('name', '')
license_text = license_data.get('full_text', '')
license_key = license_data.get('key', '')
Expand Down
Loading