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

Merge TargetRoots subclasses #5648

Merged
merged 3 commits into from
Apr 4, 2018
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
6 changes: 5 additions & 1 deletion src/python/pants/base/specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from abc import abstractmethod

from pants.util.meta import AbstractClass
from pants.util.objects import datatype
from pants.util.objects import Collection, datatype


class Spec(AbstractClass):
Expand Down Expand Up @@ -58,3 +58,7 @@ class AscendantAddresses(datatype('AscendantAddresses', ['directory']), Spec):

def to_spec_string(self):
return '{}^'.format(self.directory)


class Specs(Collection.of(Spec)):
"""A collection of Spec subclasses."""
14 changes: 1 addition & 13 deletions src/python/pants/base/target_roots.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,5 @@ class InvalidSpecConstraint(Exception):
"""Raised when invalid constraints are given via target specs and arguments like --changed*."""


class TargetRoots(object):
class TargetRoots(datatype('TargetRoots', ['specs'])):
"""Determines the target roots for a given pants run."""


class ChangedTargetRoots(datatype('ChangedTargetRoots', ['addresses']), TargetRoots):
"""Target roots that have been altered by `--changed` functionality.

Contains a list of `Address`es rather than `Spec`s, because all inputs have already been
resolved, and are known to exist.
"""


class LiteralTargetRoots(datatype('LiteralTargetRoots', ['specs']), TargetRoots):
"""User defined target roots, as pants.base.specs.Spec objects."""
11 changes: 3 additions & 8 deletions src/python/pants/bin/engine_initializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

from pants.base.build_environment import get_buildroot, get_scm
from pants.base.file_system_project_tree import FileSystemProjectTree
from pants.base.target_roots import ChangedTargetRoots, LiteralTargetRoots
from pants.engine.build_files import BuildFileAddresses, Specs, create_graph_rules
from pants.base.specs import Specs
from pants.engine.build_files import create_graph_rules
from pants.engine.fs import create_fs_rules
from pants.engine.isolated_process import create_process_rules
from pants.engine.legacy.address_mapper import LegacyAddressMapper
Expand Down Expand Up @@ -81,12 +81,7 @@ def warm_product_graph(self, target_roots):
:param TargetRoots target_roots: The targets root of the request.
"""
logger.debug('warming target_roots for: %r', target_roots)
if type(target_roots) is ChangedTargetRoots:
subjects = [BuildFileAddresses(target_roots.addresses)]
elif type(target_roots) is LiteralTargetRoots:
subjects = [Specs(tuple(target_roots.specs))]
else:
raise ValueError('Unexpected TargetRoots type: `{}`.'.format(target_roots))
subjects = [Specs(tuple(target_roots.specs))]
request = self.scheduler.execution_request([TransitiveHydratedTargets], subjects)
result = self.scheduler.execute(request)
if result.error:
Expand Down
16 changes: 4 additions & 12 deletions src/python/pants/build_graph/mutable_build_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import logging
import traceback

from pants.base.target_roots import ChangedTargetRoots, LiteralTargetRoots
from pants.build_graph.address import Address
from pants.build_graph.address_lookup_error import AddressLookupError
from pants.build_graph.build_graph import BuildGraph
Expand Down Expand Up @@ -101,17 +100,10 @@ def inject_address_closure(self, address):
.format(message=e, spec=target_address.spec))

def inject_roots_closure(self, target_roots, fail_fast=None):
if type(target_roots) is ChangedTargetRoots:
for address in target_roots.addresses:
self.inject_address_closure(address)
yield address
elif type(target_roots) is LiteralTargetRoots:
for address in self._address_mapper.scan_specs(target_roots.specs,
fail_fast=fail_fast):
self.inject_address_closure(address)
yield address
else:
raise ValueError('Unrecognized TargetRoots type: `{}`.'.format(target_roots))
for address in self._address_mapper.scan_specs(target_roots.specs,
fail_fast=fail_fast):
self.inject_address_closure(address)
yield address

def inject_specs_closure(self, specs, fail_fast=None):
for address in self._address_mapper.scan_specs(specs,
Expand Down
26 changes: 1 addition & 25 deletions src/python/pants/engine/addressable.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,15 @@

import collections
import inspect
import sys
from abc import abstractmethod
from functools import update_wrapper

import six

from pants.build_graph.address import Address, BuildFileAddress
from pants.engine.objects import Resolvable, Serializable
from pants.util.memo import memoized
from pants.util.meta import AbstractClass
from pants.util.objects import datatype


class Collection(object):
"""
Singleton Collection Type. The ambition is to gain native support for flattening,
so methods like <pants.engine.fs.merge_files> won't have to be defined separately.
Related to: https://github.com/pantsbuild/pants/issues/3169
"""

@classmethod
@memoized
def of(cls, *element_types):
union = '|'.join(element_type.__name__ for element_type in element_types)
type_name = b'{}.of({})'.format(cls.__name__, union)
supertypes = (cls, datatype('Collection', ['dependencies']))
properties = {'element_types': element_types}
collection_of_type = type(type_name, supertypes, properties)

# Expose the custom class type at the module level to be pickle compatible.
setattr(sys.modules[cls.__module__], type_name, collection_of_type)

return collection_of_type
from pants.util.objects import Collection


Addresses = Collection.of(Address)
Expand Down
11 changes: 3 additions & 8 deletions src/python/pants/engine/build_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,18 @@

from pants.base.project_tree import Dir
from pants.base.specs import (AscendantAddresses, DescendantAddresses, SiblingAddresses,
SingleAddress, Spec)
SingleAddress, Specs)
from pants.build_graph.address import Address, BuildFileAddress
from pants.build_graph.address_lookup_error import AddressLookupError
from pants.engine.addressable import (AddressableDescriptor, BuildFileAddresses, Collection,
TypeConstraintError)
from pants.engine.addressable import AddressableDescriptor, BuildFileAddresses, TypeConstraintError
from pants.engine.fs import FilesContent, PathGlobs, Snapshot
from pants.engine.mapper import AddressFamily, AddressMap, AddressMapper, ResolveError
from pants.engine.objects import Locatable, SerializableFactory, Validatable
from pants.engine.rules import RootRule, SingletonRule, TaskRule, rule
from pants.engine.selectors import Select, SelectDependencies, SelectProjection
from pants.engine.struct import Struct
from pants.util.dirutil import fast_relpath_optional
from pants.util.objects import datatype
from pants.util.objects import Collection, datatype


class ResolvedTypeMismatchError(ResolveError):
Expand All @@ -48,10 +47,6 @@ class BuildFileGlobs(datatype('BuildFilesGlobs', ['path_globs'])):
"""A wrapper around PathGlobs that are known to match a build file pattern."""


class Specs(Collection.of(Spec)):
"""A collection of Spec subclasses."""


@rule(BuildFiles,
[SelectProjection(FilesContent, PathGlobs, 'path_globs', BuildFileGlobs)])
def build_files(files_content):
Expand Down
3 changes: 1 addition & 2 deletions src/python/pants/engine/fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
from os.path import join

from pants.base.project_tree import Dir, File
from pants.engine.addressable import Collection
from pants.engine.rules import RootRule, rule
from pants.engine.selectors import Select
from pants.util.objects import datatype
from pants.util.objects import Collection, datatype


class FileContent(datatype('FileContent', ['path', 'content'])):
Expand Down
4 changes: 2 additions & 2 deletions src/python/pants/engine/legacy/address_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import os

from pants.base.build_file import BuildFile
from pants.base.specs import DescendantAddresses, SiblingAddresses
from pants.base.specs import DescendantAddresses, SiblingAddresses, Specs
from pants.build_graph.address_lookup_error import AddressLookupError
from pants.build_graph.address_mapper import AddressMapper
from pants.engine.addressable import BuildFileAddresses
from pants.engine.build_files import BuildFilesCollection, Specs
from pants.engine.build_files import BuildFilesCollection
from pants.engine.mapper import ResolveError
from pants.engine.nodes import Throw
from pants.util.dirutil import fast_relpath
Expand Down
18 changes: 5 additions & 13 deletions src/python/pants/engine/legacy/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,19 @@
from pants.backend.jvm.targets.jvm_app import Bundle, JvmApp
from pants.base.exceptions import TargetDefinitionException
from pants.base.parse_context import ParseContext
from pants.base.specs import SingleAddress
from pants.base.target_roots import ChangedTargetRoots, LiteralTargetRoots
from pants.base.specs import SingleAddress, Specs
from pants.build_graph.address import Address
from pants.build_graph.address_lookup_error import AddressLookupError
from pants.build_graph.build_graph import BuildGraph
from pants.build_graph.remote_sources import RemoteSources
from pants.engine.addressable import BuildFileAddresses, Collection
from pants.engine.build_files import Specs
from pants.engine.addressable import BuildFileAddresses
from pants.engine.fs import PathGlobs, Snapshot
from pants.engine.legacy.structs import BundleAdaptor, BundlesField, SourcesField, TargetAdaptor
from pants.engine.rules import TaskRule, rule
from pants.engine.selectors import Select, SelectDependencies, SelectProjection
from pants.source.wrapped_globs import EagerFilesetWithSpec, FilesetRelPathWrapper
from pants.util.dirutil import fast_relpath
from pants.util.objects import datatype
from pants.util.objects import Collection, datatype


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -208,14 +206,8 @@ def inject_addresses_closure(self, addresses):
pass

def inject_roots_closure(self, target_roots, fail_fast=None):
if type(target_roots) is ChangedTargetRoots:
for address in self._inject_addresses(target_roots.addresses):
yield address
elif type(target_roots) is LiteralTargetRoots:
for address in self._inject_specs(target_roots.specs):
yield address
else:
raise ValueError('Unrecognized TargetRoots type: `{}`.'.format(target_roots))
for address in self._inject_specs(target_roots.specs):
yield address

def inject_specs_closure(self, specs, fail_fast=None):
# Request loading of these specs.
Expand Down
3 changes: 1 addition & 2 deletions src/python/pants/engine/legacy/source_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@

import six

from pants.base.specs import AscendantAddresses, SingleAddress
from pants.base.specs import AscendantAddresses, SingleAddress, Specs
from pants.build_graph.address import parse_spec
from pants.build_graph.source_mapper import SourceMapper
from pants.engine.build_files import Specs
from pants.engine.legacy.address_mapper import LegacyAddressMapper
from pants.engine.legacy.graph import HydratedTargets
from pants.source.filespec import any_matches_filespec
Expand Down
7 changes: 4 additions & 3 deletions src/python/pants/init/target_roots_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

from pants.base.build_environment import get_buildroot
from pants.base.cmd_line_spec_parser import CmdLineSpecParser
from pants.base.target_roots import ChangedTargetRoots, LiteralTargetRoots
from pants.base.specs import SingleAddress
from pants.base.target_roots import TargetRoots
from pants.scm.subsystems.changed import ChangedRequest


Expand Down Expand Up @@ -64,6 +65,6 @@ def create(cls, options, build_root=None, change_calculator=None):
# alternate target roots.
changed_addresses = change_calculator.changed_target_addresses(changed_request)
logger.debug('changed addresses: %s', changed_addresses)
return ChangedTargetRoots(tuple(changed_addresses))
return TargetRoots(tuple(SingleAddress(a.spec_path, a.target_name) for a in changed_addresses))

return LiteralTargetRoots(spec_roots)
return TargetRoots(spec_roots)
3 changes: 1 addition & 2 deletions src/python/pants/scm/change_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
from collections import defaultdict

from pants.base.build_environment import get_scm
from pants.base.specs import DescendantAddresses
from pants.base.specs import DescendantAddresses, Specs
from pants.build_graph.address import Address
from pants.engine.build_files import Specs
from pants.engine.legacy.graph import TransitiveHydratedTargets, target_types_from_symbol_table
from pants.engine.legacy.source_mapper import EngineSourceMapper
from pants.goal.workspace import ScmWorkspace
Expand Down
3 changes: 3 additions & 0 deletions src/python/pants/util/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ python_library(
python_library(
name = 'objects',
sources = ['objects.py'],
dependencies = [
':memo',
],
)

python_library(
Expand Down
25 changes: 22 additions & 3 deletions src/python/pants/util/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
from __future__ import (absolute_import, division, generators, nested_scopes, print_function,
unicode_literals, with_statement)

import sys
from collections import OrderedDict, namedtuple

from pants.util.memo import memoized

def datatype(*args, **kwargs):
"""A wrapper for `namedtuple` that accounts for the type of the object in equality.

"""
def datatype(*args, **kwargs):
"""A wrapper for `namedtuple` that accounts for the type of the object in equality."""
class DataType(namedtuple(*args, **kwargs)):
__slots__ = ()

Expand Down Expand Up @@ -49,3 +50,21 @@ def __getnewargs__(self):
return tuple(super(DataType, self).__iter__())

return DataType


class Collection(object):
"""Constructs classes representing collections of objects of a particular type."""

@classmethod
@memoized
def of(cls, *element_types):
union = '|'.join(element_type.__name__ for element_type in element_types)
type_name = b'{}.of({})'.format(cls.__name__, union)
supertypes = (cls, datatype('Collection', ['dependencies']))
properties = {'element_types': element_types}
collection_of_type = type(type_name, supertypes, properties)

# Expose the custom class type at the module level to be pickle compatible.
setattr(sys.modules[cls.__module__], type_name, collection_of_type)

return collection_of_type
7 changes: 4 additions & 3 deletions tests/python/pants_test/engine/test_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
from contextlib import contextmanager
from textwrap import dedent

from pants.base.specs import DescendantAddresses, SiblingAddresses, SingleAddress
from pants.base.specs import DescendantAddresses, SiblingAddresses, SingleAddress, Specs
from pants.build_graph.address import Address
from pants.engine.addressable import BuildFileAddresses, Collection
from pants.engine.build_files import Specs, UnhydratedStruct, create_graph_rules
from pants.engine.addressable import BuildFileAddresses
from pants.engine.build_files import UnhydratedStruct, create_graph_rules
from pants.engine.fs import create_fs_rules
from pants.engine.mapper import (AddressFamily, AddressMap, AddressMapper, DifferingFamiliesError,
DuplicateNameError, UnaddressableObjectError)
Expand All @@ -22,6 +22,7 @@
from pants.engine.selectors import SelectDependencies
from pants.engine.struct import Struct
from pants.util.dirutil import safe_open
from pants.util.objects import Collection
from pants_test.engine.examples.parsers import JsonParser
from pants_test.engine.scheduler_test_base import SchedulerTestBase
from pants_test.engine.util import Target, TargetTable
Expand Down
2 changes: 1 addition & 1 deletion tests/python/pants_test/engine/test_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
from textwrap import dedent

from pants.base.cmd_line_spec_parser import CmdLineSpecParser
from pants.base.specs import Specs
from pants.build_graph.address import Address
from pants.engine.addressable import BuildFileAddresses
from pants.engine.build_files import Specs
from pants.engine.nodes import Return, Throw
from pants.engine.rules import RootRule, TaskRule
from pants.engine.selectors import Select, SelectVariant
Expand Down