Skip to content
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ docs/_build
/.cache/

/share/
/local/
/local/
/.pytest_cache/
2 changes: 1 addition & 1 deletion etc/conf/dev/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ py
colorama
pytest
pluggy
tox
aboutcode-toolkit
45 changes: 27 additions & 18 deletions etc/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.


"""
This script a configuration helper to select pip requirement files to install
and python and shell configuration scripts to execute based on provided config
Expand Down Expand Up @@ -74,7 +73,6 @@
import shutil
import subprocess


# platform-specific file base names
sys_platform = str(sys.platform).lower()
on_win = False
Expand All @@ -89,7 +87,6 @@
raise Exception('Unsupported OS/platform')
platform_names = tuple()


# common file basenames for requirements and scripts
base = ('base',)

Expand All @@ -108,9 +105,12 @@
shell_scripts = ('win.bat',)


def call(cmd, root_dir):
def call(cmd, root_dir, quiet=True):
""" Run a `cmd` command (as a list of args) with all env vars."""
cmd = ' '.join(cmd)
if not quiet:
print(' Running command:', repr(cmd))

if subprocess.Popen(cmd, shell=True, env=dict(os.environ), cwd=root_dir).wait() != 0:
print()
print('Failed to execute command:\n%(cmd)s. Aborting...' % locals())
Expand Down Expand Up @@ -188,7 +188,7 @@ def create_virtualenv(std_python, root_dir, tpp_dirs, quiet=False):
components.
"""
if not quiet:
print("* Configuring Python ...")
print('* Configuring Python ...')
# search virtualenv.py in the tpp_dirs. keep the first found
venv_py = None
for tpd in tpp_dirs:
Expand All @@ -199,7 +199,7 @@ def create_virtualenv(std_python, root_dir, tpp_dirs, quiet=False):

# error out if venv_py not found
if not venv_py:
print("Configuration Error ... aborting.")
print('Configuration Error ... aborting.')
exit(1)

vcmd = [std_python, venv_py, '--never-download']
Expand All @@ -209,12 +209,12 @@ def create_virtualenv(std_python, root_dir, tpp_dirs, quiet=False):
vcmd.extend(build_pip_dirs_args(tpp_dirs, root_dir))
# we create the virtualenv in the root_dir
vcmd.append('"' + root_dir + '"')
call(vcmd, root_dir)
call(vcmd, root_dir, quiet)


def activate(root_dir):
""" Activate a virtualenv in the current process."""
print("* Activating ...")
print('* Activating ...')
bin_dir = os.path.join(root_dir, 'bin')
activate_this = os.path.join(bin_dir, 'activate_this.py')
with open(activate_this) as f:
Expand All @@ -228,30 +228,36 @@ def install_3pp(configs, root_dir, tpp_dirs, quiet=False):
using the vendored components in `tpp_dirs`.
"""
if not quiet:
print("* Installing components ...")
print('* Installing components ...')
requirement_files = get_conf_files(configs, root_dir, requirements)
for req_file in requirement_files:
pcmd = ['pip', 'install', '--no-allow-external',
'--use-wheel', '--no-index', '--no-cache-dir']
if on_win:
pcmd = ['python', '-m']
else:
pcmd = []
pcmd += ['pip', 'install', '--no-index', '--no-cache-dir']
if quiet:
pcmd += ['--quiet']
if on_win:
pcmd += ['--verbose', '--verbose', '--verbose']

pip_dir_args = list(build_pip_dirs_args(tpp_dirs, root_dir, '--find-links='))
pcmd.extend(pip_dir_args)
req_loc = os.path.join(root_dir, req_file)
pcmd.extend(['-r' , '"' + req_loc + '"'])
call(pcmd, root_dir)
call(pcmd, root_dir, quiet)


def run_scripts(configs, root_dir, configured_python, quiet=False):
"""
Run Python scripts and shell scripts found in `configs`.
"""
if not quiet:
print("* Configuring ...")
print('* Configuring ...')
# Run Python scripts for each configurations
for py_script in get_conf_files(configs, root_dir, python_scripts):
cmd = [configured_python, '"' + os.path.join(root_dir, py_script) + '"']
call(cmd, root_dir)
call(cmd, root_dir, quiet)

# Run sh_script scripts for each configurations
for sh_script in get_conf_files(configs, root_dir, shell_scripts):
Expand All @@ -260,7 +266,7 @@ def run_scripts(configs, root_dir, configured_python, quiet=False):
if on_win:
cmd = []
cmd = cmd + [os.path.join(root_dir, sh_script)]
call(cmd, root_dir)
call(cmd, root_dir, quiet)


def chmod_bin(directory):
Expand Down Expand Up @@ -353,8 +359,11 @@ def get_conf_files(config_dir_paths, root_dir, file_names=requirements):
if not os.path.exists(scripts_dir):
os.makedirs(scripts_dir)
if not os.path.exists(bin_dir):
cmd = ('mklink /J "%(bin_dir)s" "%(scripts_dir)s"' % locals()).split()
call(cmd, root_dir)
cmd = [
'mklink', '/J',
'"%(bin_dir)s"' % locals(),
'"%(scripts_dir)s"' % locals()]
call(cmd, root_dir, run_quiet)
else:
configured_python = os.path.join(bin_dir, 'python')
scripts_dir = bin_dir
Expand Down Expand Up @@ -399,5 +408,5 @@ def get_conf_files(config_dir_paths, root_dir, file_names=requirements):
run_scripts(configs, root_dir, configured_python, quiet=run_quiet)
chmod_bin(bin_dir)
if not run_quiet:
print("* Configuration completed.")
print('* Configuration completed.')
print()
88 changes: 65 additions & 23 deletions src/license_expression/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,6 @@ class Licensing(boolean.BooleanAlgebra):
... ]
>>> assert expected == l.license_symbols(parsed)
>>> assert expected == l.license_symbols(expression)

This is set at runtime during parsing:

>>> assert l.license_symbols(parsed)[1].as_exception

"""

def __init__(self, symbols=tuple(), quiet=True):
Expand Down Expand Up @@ -360,8 +355,6 @@ def parse(self, expression, validate=False, strict=False, **kwargs):
such as "XXX with ZZZ" if the XXX symbol has `is_exception` set to True or
the YYY symbol has `is_exception` set to False.

When a symbol used as an exception its attribute `as_exception` is set to True.

For example:
>>> expression = 'EPL-1.0 and Apache-1.1 OR GPL-2.0 with Classpath-exception'
>>> parsed = Licensing().parse(expression)
Expand Down Expand Up @@ -664,9 +657,6 @@ def __init__(self, key, aliases=tuple(), is_exception=False, *args, **kwargs):
self.aliases = aliases and tuple(aliases) or tuple()
self.is_exception = is_exception

# set at runtime based on parsing when the symbol was used as an exception
self.as_exception = False

# super only know about a single "obj" object.
super(LicenseSymbol, self).__init__(self.key)

Expand All @@ -680,14 +670,25 @@ def __hash__(self, *args, **kwargs):
return hash((self.key, self.is_exception))

def __eq__(self, other):
return (self is other
or (isinstance(other, self.__class__)
and self.key == other.key
and self.is_exception == other.is_exception)
or (self.symbol_like(other)
and self.key == other.key
and self.is_exception == other.is_exception)
)
if self is other:
return True
if not (isinstance(other, self.__class__) or self.symbol_like(other)):
return False
return self.key == other.key and self.is_exception == other.is_exception

def __ne__(self, other):
if self is other:
return False
if not (isinstance(other, self.__class__) or self.symbol_like(other)):
return True
return (self.key != other.key or self.is_exception != other.is_exception)

def __lt__(self, other):
if isinstance(
other, (LicenseSymbol, LicenseWithExceptionSymbol, LicenseSymbolLike)):
return str(self) < str(other)
else:
return NotImplemented

__nonzero__ = __bool__ = lambda s: True

Expand Down Expand Up @@ -749,6 +750,32 @@ def render(self, template='{symbol.key}', *args, **kwargs):
return self._render(template, *args, **kwargs)
return super(LicenseSymbolLike, self).render(template, *args, **kwargs)

__nonzero__ = __bool__ = lambda s: True

def __hash__(self, *args, **kwargs):
return hash((self.key, self.is_exception))

def __eq__(self, other):
if self is other:
return True
if not (isinstance(other, self.__class__) or self.symbol_like(other)):
return False
return self.key == other.key and self.is_exception == other.is_exception

def __ne__(self, other):
if self is other:
return False
if not (isinstance(other, self.__class__) or self.symbol_like(other)):
return True
return (self.key != other.key or self.is_exception != other.is_exception)

def __lt__(self, other):
if isinstance(
other, (LicenseSymbol, LicenseWithExceptionSymbol, LicenseSymbolLike)):
return str(self) < str(other)
else:
return NotImplemented


#FIXME: we need to implement comparison!!!!
@total_ordering
Expand Down Expand Up @@ -786,8 +813,6 @@ def __init__(self, license_symbol, exception_symbol, strict=False, *args, **kwar
'exception_symbol must be an exception with "is_exception" set to True: %(exception_symbol)r' % locals())

self.license_symbol = license_symbol

exception_symbol.as_exception = True
self.exception_symbol = exception_symbol

super(LicenseWithExceptionSymbol, self).__init__(str(self))
Expand All @@ -808,11 +833,28 @@ def __hash__(self, *args, **kwargs):
return hash((self.license_symbol, self.exception_symbol,))

def __eq__(self, other):
return self is other or (
isinstance(other, self.__class__)
and self.license_symbol == other.license_symbol
if self is other:
return True
if not isinstance(other, self.__class__):
return False
return (self.license_symbol == other.license_symbol
and self.exception_symbol == other.exception_symbol)

def __ne__(self, other):
if self is other:
return False
if not isinstance(other, self.__class__):
return True
return not (self.license_symbol == other.license_symbol
and self.exception_symbol == other.exception_symbol)

def __lt__(self, other):
if isinstance(
other, (LicenseSymbol, LicenseWithExceptionSymbol, LicenseSymbolLike)):
return str(self) < str(other)
else:
return NotImplemented

__nonzero__ = __bool__ = lambda s: True

def __str__(self):
Expand Down
37 changes: 37 additions & 0 deletions tests/test_license_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from license_expression import Licensing
from license_expression import LicenseExpression
from license_expression import LicenseSymbol
from license_expression import LicenseSymbolLike
from license_expression import LicenseWithExceptionSymbol
from license_expression import ParseError
from license_expression import Result
Expand Down Expand Up @@ -1624,3 +1625,39 @@ def test_is_equivalent_with_symbols_and_complex_expression(self):
assert not licensing1.is_equivalent(parsed1, parsed3)
assert not licensing2.is_equivalent(parsed1, parsed3)
assert not licensing_no_sym.is_equivalent(parsed1, parsed3)

def test_all_symbol_classes_can_compare_and_sort(self):
l1 = LicenseSymbol('a')
l2 = LicenseSymbol('b')
lx = LicenseWithExceptionSymbol(l1, l2)
lx2 = LicenseWithExceptionSymbol(l1, l2)
assert not (lx < lx2)
assert not (lx2 < lx)
assert lx2 == lx
assert not (lx2 != lx)
assert l1 < l2
assert l2 > l1
assert not (l2 == l1)
assert l2 != l1

class SymLike(object):

def __init__(self, key, is_exception=False):
self.key = key
self.is_exception = is_exception

l3 = LicenseSymbolLike(SymLike('b'))
lx3 = LicenseWithExceptionSymbol(l1, l3)
assert not (lx < lx3)
assert not (lx3 < lx)
assert lx3 == lx
assert hash(lx3) == hash(lx)
assert not (lx3 != lx)

assert l2 == l3
assert hash(l2) == hash(l3)

l4 = LicenseSymbolLike(SymLike('c'))

expected = [l1, lx, lx2, lx3, l3, l2, l4]
assert expected == sorted([l4, l3, l2, l1, lx , lx2, lx3])
Binary file not shown.
Binary file not shown.
18 changes: 18 additions & 0 deletions thirdparty/base/certifi-2018.4.16-py2.py3-none-any.whl.ABOUT
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
about_resource: certifi-2018.4.16-py2.py3-none-any.whl
checksum_md5: 8280b65d50546025140b542904e86c3b
checksum_sha1: 760c62185c36483f7f7b9db7788c699e9c735990
contact: me@kennethreitz.com
copyright: Kenneth Reitz
description: Certifi is a carefully curated collection of Root Certificates for validating
the trustworthiness of SSL certificates while verifying the identity of TLS hosts.
It has been extracted from the Requests project.
download_url: https://files.pythonhosted.org/packages/7c/e6/92ad559b7192d846975fc916b65f667c7b8c3a32bea7372340bfe9a15fa5/certifi-2018.4.16-py2.py3-none-any.whl#sha256=9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0
homepage_url: https://certifi.io/en/latest/
license_expression: mpl-2.0
name: certifi
notice_url: https://certifi.io/en/latest/
notice_file: certifi.NOTICE
license_file: mpl-2.0.LICENSE
owner: Kenneth Reitz
owner_url: https://github.com/kennethreitz
version: 2018.4.16
14 changes: 0 additions & 14 deletions thirdparty/base/certifi.ABOUT

This file was deleted.

Loading