Skip to content

Commit

Permalink
Basic implementation of pluggable spaces.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikepurvis committed May 27, 2017
1 parent 8b2d68f commit 50017fc
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 141 deletions.
4 changes: 2 additions & 2 deletions catkin_tools/argument_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ def add_cmake_and_make_and_catkin_make_args(parser):

add = parser.add_mutually_exclusive_group().add_argument
add('--make-args', metavar='ARG', dest='make_args', nargs='+', required=False, type=str, default=None,
help='Arbitrary arguments which are passes to make.'
help='Arbitrary arguments which are passes to make. '
'It collects all of following arguments until a "--" is read.')
add('--no-make-args', dest='make_args', action='store_const', const=[], default=None,
help='Pass no additional arguments to make (does not affect --catkin-make-args).')

add = parser.add_mutually_exclusive_group().add_argument
add('--catkin-make-args', metavar='ARG', dest='catkin_make_args',
nargs='+', required=False, type=str, default=None,
help='Arbitrary arguments which are passes to make but only for catkin packages.'
help='Arbitrary arguments which are passes to make but only for catkin packages. '
'It collects all of following arguments until a "--" is read.')
add('--no-catkin-make-args', dest='catkin_make_args', action='store_const', const=[], default=None,
help='Pass no additional arguments to make for catkin packages (does not affect --make-args).')
Expand Down
174 changes: 65 additions & 109 deletions catkin_tools/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,12 @@ class Context(object):
This context can be locked, so that changing the members is prevented.
"""

DEFAULT_LOG_SPACE = 'logs'
DEFAULT_SOURCE_SPACE = 'src'
DEFAULT_BUILD_SPACE = 'build'
DEFAULT_DEVEL_SPACE = 'devel'
DEFAULT_INSTALL_SPACE = 'install'
CATKIN_SPACES_GROUP = 'catkin_tools.spaces'

SPACES = {}

STORED_KEYS = [
'extend_path',
'source_space',
'log_space',
'build_space',
'devel_space',
'install_space',
'devel_layout',
'install',
'isolate_install',
Expand All @@ -75,12 +68,57 @@ class Context(object):
'blacklist',
]

KEYS = STORED_KEYS + [
EXTRA_KEYS = [
'workspace',
'profile',
'space_suffix',
]

KEYS = []

@classmethod
def _create_space_methods(cls, space):
def space_abs_getter(self):
return getattr(self, '__%s_space_abs' % space)

def space_getter(self):
return getattr(self, '__%s_space' % space)

def space_setter(self, value):
if self.__locked:
raise RuntimeError("Setting of context members is not allowed while locked.")
setattr(self, '__%s_space' % space, value)
setattr(self, '__%s_space_abs' % space, os.path.join(self.__workspace, value))

def space_exists(self):
"Returns true if the space exists"
space_abs = getattr(self, '__%s_space_abs' % space)
return os.path.exists(space_abs) and os.path.isdir(space_abs)

setattr(cls, '%s_space' % space, property(space_getter, space_setter))
setattr(cls, '%s_space_abs' % space, property(space_abs_getter))
setattr(cls, '%s_space_exists' % space, space_exists)

@classmethod
def setup_space_keys(cls):
'''
To be called one time on initial use. Initializes the SPACE_KEYS
class members and associated member functions based on available
space plugins.
'''
if cls.KEYS:
return

from pkg_resources import iter_entry_points

for entry_point in iter_entry_points(group=cls.CATKIN_SPACES_GROUP):
ep_dict = entry_point.load()
cls.STORED_KEYS.append(entry_point.name + '_space')
cls.SPACES[entry_point.name] = ep_dict
cls._create_space_methods(entry_point.name)

cls.KEYS = cls.STORED_KEYS + cls.EXTRA_KEYS

@classmethod
def load(
cls,
Expand Down Expand Up @@ -125,6 +163,7 @@ def load(
:returns: A potentially valid Context object constructed from the given arguments
:rtype: Context
"""
Context.setup_space_keys()

# Initialize dictionary version of opts namespace
opts_vars = vars(opts) if opts else {}
Expand Down Expand Up @@ -194,11 +233,6 @@ def __init__(
workspace=None,
profile=None,
extend_path=None,
source_space=None,
log_space=None,
build_space=None,
devel_space=None,
install_space=None,
devel_layout=None,
install=False,
isolate_install=False,
Expand Down Expand Up @@ -264,19 +298,20 @@ def __init__(
print('Warning: Unhandled config context options: {}'.format(kwargs), file=sys.stderr)

# Validation is done on assignment
# Handle *space assignment and defaults
self.workspace = workspace

self.extend_path = extend_path if extend_path else None
ss = '' if space_suffix is None else space_suffix

self.profile = profile

self.source_space = Context.DEFAULT_SOURCE_SPACE if source_space is None else source_space
self.log_space = Context.DEFAULT_LOG_SPACE + ss if ss or log_space is None else log_space
self.build_space = Context.DEFAULT_BUILD_SPACE + ss if ss or build_space is None else build_space
self.devel_space = Context.DEFAULT_DEVEL_SPACE + ss if ss or devel_space is None else devel_space
self.install_space = Context.DEFAULT_INSTALL_SPACE + ss if ss or install_space is None else install_space
# Handle *space assignment and defaults
for space, space_dict in Context.SPACES.items():
key_name = space + '_space'
default = space_dict['default']
if space_suffix and space != 'source':
default += space_suffix
setattr(self, key_name, kwargs.get(key_name, default))

self.destdir = os.environ['DESTDIR'] if 'DESTDIR' in os.environ else None

# Handle package whitelist/blacklist
Expand Down Expand Up @@ -411,20 +446,20 @@ def summary(self, notes=[]):
"--init`.")]
if not self.source_space_exists():
summary_warnings += [clr(
"Source space `@{yf}{_Context__source_space_abs}@|` does not yet exist.")]
"Source space `@{yf}{__source_space_abs}@|` does not yet exist.")]

spaces_summary = []
for space, space_dict in sorted(Context.SPACES.items()):
spaces_summary.append(
clr('@{cf}' + space_dict['space'] + ':@|' + ' ' * (18 - len(space_dict['space'])) +
'{' + space + '_missing} @{yf}{__' + space + '_space_abs}@|'))
summary = [
[
clr("@{cf}Profile:@| @{yf}{profile}@|"),
clr("@{cf}Extending:@| {extend_mode} @{yf}{extend}@|"),
clr("@{cf}Workspace:@| @{yf}{_Context__workspace}@|"),
],
[
clr("@{cf}Source Space:@| {source_missing} @{yf}{_Context__source_space_abs}@|"),
clr("@{cf}Log Space:@| {log_missing} @{yf}{_Context__log_space_abs}@|"),
clr("@{cf}Build Space:@| {build_missing} @{yf}{_Context__build_space_abs}@|"),
clr("@{cf}Devel Space:@| {devel_missing} @{yf}{_Context__devel_space_abs}@|"),
clr("@{cf}Install Space:@| {install_missing} @{yf}{_Context__install_space_abs}@|"),
spaces_summary + [
clr("@{cf}DESTDIR:@| {destdir_missing} @{yf}{_Context__destdir}@|")
],
[
Expand Down Expand Up @@ -547,89 +582,10 @@ def extend_path(self, value):
raise ValueError("Resultspace path '{0}' does not exist.".format(value))
self.__extend_path = value

@property
def source_space_abs(self):
return self.__source_space_abs

@property
def source_space(self):
return self.__source_space

@source_space.setter
def source_space(self, value):
if self.__locked:
raise RuntimeError("Setting of context members is not allowed while locked.")
self.__source_space = value
self.__source_space_abs = os.path.join(self.__workspace, value)

def source_space_exists(self):
"Returns true if the source space exists"
return os.path.exists(self.source_space_abs) and os.path.isdir(self.source_space_abs)

def initialized(self):
"""Check if this context is initialized."""
return self.workspace == find_enclosing_workspace(self.workspace)

@property
def log_space_abs(self):
return self.__log_space_abs

@property
def log_space(self):
return self.__log_space

@log_space.setter
def log_space(self, value):
if self.__locked:
raise RuntimeError("Setting of context members is not allowed while locked.")
self.__log_space = value
self.__log_space_abs = os.path.join(self.__workspace, value)

@property
def build_space_abs(self):
return self.__build_space_abs

@property
def build_space(self):
return self.__build_space

@build_space.setter
def build_space(self, value):
if self.__locked:
raise RuntimeError("Setting of context members is not allowed while locked.")
self.__build_space = value
self.__build_space_abs = os.path.join(self.__workspace, value)

@property
def devel_space_abs(self):
return self.__devel_space_abs

@property
def devel_space(self):
return self.__devel_space

@devel_space.setter
def devel_space(self, value):
if self.__locked:
raise RuntimeError("Setting of context members is not allowed while locked.")
self.__devel_space = value
self.__devel_space_abs = os.path.join(self.__workspace, value)

@property
def install_space_abs(self):
return self.__install_space_abs

@property
def install_space(self):
return self.__install_space

@install_space.setter
def install_space(self, value):
if self.__locked:
raise RuntimeError("Setting of context members is not allowed while locked.")
self.__install_space = value
self.__install_space_abs = os.path.join(self.__workspace, value)

@property
def destdir(self):
return self.__destdir
Expand Down
Empty file added catkin_tools/spaces/__init__.py
Empty file.
20 changes: 20 additions & 0 deletions catkin_tools/spaces/build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2017 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

description = dict(
default='build',
short_flag='-b',
space='Build Space',
description='Intermediate generated files are placed in this location.'
)
21 changes: 21 additions & 0 deletions catkin_tools/spaces/devel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2017 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

description = dict(
default='devel',
short_flag='-d',
space='Devel Space',
description='This result space contains compiled products but ' +
'references the source space for static assets and scripts.'
)
20 changes: 20 additions & 0 deletions catkin_tools/spaces/install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2017 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

description = dict(
default='install',
short_flag='-i',
space='Install Space',
description='Self-contained installation result space.'
)
20 changes: 20 additions & 0 deletions catkin_tools/spaces/log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2017 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

description = dict(
default='logs',
short_flag='-l',
space='Log Space',
description='Output generated during the build stages.'
)
20 changes: 20 additions & 0 deletions catkin_tools/spaces/source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2017 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

description = dict(
default='src',
short_flag='-s',
space='Source Space',
description='Source files, should not be modified by build system.'
)
Loading

0 comments on commit 50017fc

Please sign in to comment.