def rules(): return ( *ancestor_files.rules(), *coverage_py.rules(), *dependency_inference_rules.rules(), *export.rules(), *ipython.rules(), *local_dists.rules(), *lockfile.rules(), *package_pex_binary.rules(), *pex.rules(), *pex_cli.rules(), *pex_environment.rules(), *pex_from_targets.rules(), *pytest.rules(), *pytest_runner.rules(), *python_native_code.rules(), *python_sources.rules(), *repl.rules(), *run_pex_binary.rules(), *setup_py.rules(), *setuptools.rules(), *tailor.rules(), *target_types_rules.rules(), # Macros. *deprecation_fixers.rules(), *pipenv_requirements.rules(), *poetry_requirements.rules(), *python_requirements.rules(), )
def rules(): return ( *collect_rules(), *lockfile.rules(), *python_sources.rules(), UnionRule(GenerateToolLockfileSentinel, Flake8LockfileSentinel), )
def assert_sources( expected_files, expected_packages, expected_namespace_packages, expected_package_data, addrs, ): rule_runner = create_setup_py_rule_runner( rules=[ get_sources, get_owned_dependencies, get_exporting_owner, *target_types_rules.rules(), *python_sources.rules(), QueryRule(OwnedDependencies, (DependencyOwner,)), QueryRule(DistBuildSources, (DistBuildChrootRequest,)), ] ) rule_runner.write_files( { "src/python/foo/bar/baz/BUILD": textwrap.dedent( """ python_sources(name='baz1', sources=['baz1.py']) python_sources(name='baz2', sources=['baz2.py']) """ ), "src/python/foo/bar/baz/baz1.py": "", "src/python/foo/bar/baz/baz2.py": "", "src/python/foo/bar/__init__.py": _namespace_decl, "src/python/foo/qux/BUILD": "python_sources()", "src/python/foo/qux/__init__.py": "", "src/python/foo/qux/qux.py": "", "src/python/foo/resources/BUILD": 'resource(source="js/code.js")', "src/python/foo/resources/js/code.js": "", "src/python/foo/__init__.py": "", # We synthesize an owner for the addrs, so we have something to put in SetupPyChrootRequest. "src/python/foo/BUILD": textwrap.dedent( f""" python_distribution( name="dist", dependencies=["{'","'.join(addr.spec for addr in addrs)}"], provides=setup_py(name="foo", version="3.2.1"), ) """ ), } ) owner_tgt = rule_runner.get_target(Address("src/python/foo", target_name="dist")) srcs = rule_runner.request( DistBuildSources, [DistBuildChrootRequest(ExportedTarget(owner_tgt), py2=False)], ) chroot_snapshot = rule_runner.request(Snapshot, [srcs.digest]) assert sorted(expected_files) == sorted(chroot_snapshot.files) assert sorted(expected_packages) == sorted(srcs.packages) assert sorted(expected_namespace_packages) == sorted(srcs.namespace_packages) assert expected_package_data == dict(srcs.package_data)
def test_no_dist_type_selected() -> None: rule_runner = RuleRunner( rules=[ determine_explicitly_provided_setup_kwargs, generate_chroot, generate_setup_py, determine_finalized_setup_kwargs, get_sources, get_requirements, get_owned_dependencies, get_exporting_owner, package_python_dist, *dists.rules(), *python_sources.rules(), *target_types_rules.rules(), SubsystemRule(SetupPyGeneration), QueryRule(BuiltPackage, (PythonDistributionFieldSet,)), ], target_types=[PythonDistribution], objects={"setup_py": PythonArtifact}, ) rule_runner.write_files( { "src/python/aaa/BUILD": textwrap.dedent( """ python_distribution( name='aaa', provides=setup_py(name='aaa', version='2.2.2'), wheel=False, sdist=False ) """ ), } ) address = Address("src/python/aaa", target_name="aaa") with pytest.raises(ExecutionError) as exc_info: rule_runner.request( BuiltPackage, inputs=[ PythonDistributionFieldSet( address=address, provides=PythonProvidesField( PythonArtifact(name="aaa", version="2.2.2"), address ), ) ], ) assert 1 == len(exc_info.value.wrapped_exceptions) wrapped_exception = exc_info.value.wrapped_exceptions[0] assert isinstance(wrapped_exception, NoDistTypeSelected) assert ( "In order to package src/python/aaa:aaa at least one of 'wheel' or 'sdist' must be `True`." == str(wrapped_exception) )
def rule_runner() -> RuleRunner: return RuleRunner( rules=[ *subsystem_rules(), *skip_field.rules(), *python_sources.rules(), QueryRule(PylintFirstPartyPlugins, []), QueryRule(PythonLockfileRequest, [PylintLockfileSentinel]), ], target_types=[PythonLibrary, GenericTarget, PythonRequirementLibrary], )
def rule_runner() -> RuleRunner: return RuleRunner( rules=[ *subsystem_rules(), *skip_field.rules(), *python_sources.rules(), *target_types_rules.rules(), QueryRule(Flake8FirstPartyPlugins, []), QueryRule(GeneratePythonLockfile, [Flake8LockfileSentinel]), ], target_types=[PythonSourcesGeneratorTarget, GenericTarget, PythonRequirementTarget], )
def test_pex_binary_targets() -> None: rule_runner = RuleRunner( rules=[ *target_types_rules.rules(), *import_rules(), *python_sources.rules(), QueryRule(_TargetParametrizations, [_TargetParametrizationsRequest]), ], target_types=[PexBinariesGeneratorTarget], ) rule_runner.write_files( { "src/py/BUILD": dedent( """\ pex_binaries( name="pexes", entry_points=[ "f1.py", "f2:foo", "subdir.f.py", "subdir.f:main", ], overrides={ 'f2:foo': {'tags': ['overridden']}, 'subdir.f.py': {'tags': ['overridden']}, } ) """ ), } ) def gen_pex_binary_tgt(entry_point: str, tags: list[str] | None = None) -> PexBinary: return PexBinary( {PexEntryPointField.alias: entry_point, Tags.alias: tags}, Address("src/py", target_name="pexes", generated_name=entry_point.replace(":", "-")), residence_dir="src/py", ) result = rule_runner.request( _TargetParametrizations, [ _TargetParametrizationsRequest( Address("src/py", target_name="pexes"), description_of_origin="tests" ) ], ).parametrizations.values() assert set(result) == { gen_pex_binary_tgt("f1.py"), gen_pex_binary_tgt("f2:foo", tags=["overridden"]), gen_pex_binary_tgt("subdir.f.py", tags=["overridden"]), gen_pex_binary_tgt("subdir.f:main"), }
def rule_runner() -> RuleRunner: return RuleRunner( rules=[ *flake8_rules(), *flake8_subsystem_rules(), *python_sources.rules(), *config_files.rules(), *target_types_rules.rules(), QueryRule(LintResults, [Flake8Request]), ], target_types=[PythonSourcesGeneratorTarget], )
def chroot_rule_runner() -> RuleRunner: return create_setup_py_rule_runner(rules=[ determine_setup_kwargs, generate_chroot, get_sources, get_requirements, get_owned_dependencies, get_exporting_owner, *python_sources.rules(), setup_kwargs_plugin, UnionRule(SetupKwargsRequest, PluginSetupKwargsRequest), QueryRule(SetupPyChroot, (SetupPyChrootRequest, )), ])
def rule_runner() -> RuleRunner: return RuleRunner( rules=[ *subsystem.rules(), *skip_field.rules(), *config_files.rules(), *python_sources.rules(), *target_types_rules.rules(), QueryRule(MyPyConfigFile, []), QueryRule(MyPyFirstPartyPlugins, []), QueryRule(PythonLockfileRequest, [MyPyLockfileSentinel]), ], target_types=[ PythonSourcesGeneratorTarget, PythonRequirementTarget, GenericTarget ], )
def rules(): return ( *coverage_py.rules(), *tailor.rules(), *ancestor_files.rules(), *python_sources.rules(), *dependency_inference_rules.rules(), *pex.rules(), *pex_cli.rules(), *pex_environment.rules(), *pex_from_targets.rules(), *pytest_runner.rules(), *package_pex_binary.rules(), *python_native_code.rules(), *repl.rules(), *run_pex_binary.rules(), *target_types_rules.rules(), *setup_py.rules(), )
def chroot_rule_runner() -> RuleRunner: return create_setup_py_rule_runner( rules=[ determine_setup_kwargs, generate_chroot, generate_setup_py, generate_setup_py_kwargs, get_sources, get_requirements, get_owned_dependencies, get_exporting_owner, *python_sources.rules(), *target_types_rules.rules(), setup_kwargs_plugin, SubsystemRule(SetupPyGeneration), UnionRule(SetupKwargsRequest, PluginSetupKwargsRequest), QueryRule(DistBuildChroot, (DistBuildChrootRequest,)), QueryRule(DistBuildSources, (DistBuildChrootRequest,)), QueryRule(FinalizedSetupKwargs, (GenerateSetupPyRequest,)), ] )
def test_get_sources() -> None: rule_runner = create_setup_py_rule_runner(rules=[ get_sources, *python_sources.rules(), QueryRule(SetupPySources, (SetupPySourcesRequest, )), ]) rule_runner.add_to_build_file( "src/python/foo/bar/baz", textwrap.dedent(""" python_library(name='baz1', sources=['baz1.py']) python_library(name='baz2', sources=['baz2.py']) """), ) rule_runner.create_file("src/python/foo/bar/baz/baz1.py") rule_runner.create_file("src/python/foo/bar/baz/baz2.py") rule_runner.create_file("src/python/foo/bar/__init__.py", _namespace_decl) rule_runner.add_to_build_file("src/python/foo/qux", "python_library()") rule_runner.create_file("src/python/foo/qux/__init__.py") rule_runner.create_file("src/python/foo/qux/qux.py") rule_runner.add_to_build_file("src/python/foo/resources", 'resources(sources=["js/code.js"])') rule_runner.create_file("src/python/foo/resources/js/code.js") rule_runner.create_file("src/python/foo/__init__.py") def assert_sources( expected_files, expected_packages, expected_namespace_packages, expected_package_data, addrs, ): targets = Targets(rule_runner.get_target(addr) for addr in addrs) srcs = rule_runner.request( SetupPySources, [SetupPySourcesRequest(targets, py2=False)], ) chroot_snapshot = rule_runner.request(Snapshot, [srcs.digest]) assert sorted(expected_files) == sorted(chroot_snapshot.files) assert sorted(expected_packages) == sorted(srcs.packages) assert sorted(expected_namespace_packages) == sorted( srcs.namespace_packages) assert expected_package_data == dict(srcs.package_data) assert_sources( expected_files=[ "foo/bar/baz/baz1.py", "foo/bar/__init__.py", "foo/__init__.py" ], expected_packages=["foo", "foo.bar", "foo.bar.baz"], expected_namespace_packages=["foo.bar"], expected_package_data={}, addrs=[Address("src/python/foo/bar/baz", target_name="baz1")], ) assert_sources( expected_files=[ "foo/bar/baz/baz2.py", "foo/bar/__init__.py", "foo/__init__.py" ], expected_packages=["foo", "foo.bar", "foo.bar.baz"], expected_namespace_packages=["foo.bar"], expected_package_data={}, addrs=[Address("src/python/foo/bar/baz", target_name="baz2")], ) assert_sources( expected_files=[ "foo/qux/qux.py", "foo/qux/__init__.py", "foo/__init__.py" ], expected_packages=["foo", "foo.qux"], expected_namespace_packages=[], expected_package_data={}, addrs=[Address("src/python/foo/qux")], ) assert_sources( expected_files=[ "foo/bar/baz/baz1.py", "foo/bar/__init__.py", "foo/qux/qux.py", "foo/qux/__init__.py", "foo/__init__.py", "foo/resources/js/code.js", ], expected_packages=["foo", "foo.bar", "foo.bar.baz", "foo.qux"], expected_namespace_packages=["foo.bar"], expected_package_data={"foo": ("resources/js/code.js", )}, addrs=[ Address("src/python/foo/bar/baz", target_name="baz1"), Address("src/python/foo/qux"), Address("src/python/foo/resources"), ], ) assert_sources( expected_files=[ "foo/bar/baz/baz1.py", "foo/bar/baz/baz2.py", "foo/bar/__init__.py", "foo/qux/qux.py", "foo/qux/__init__.py", "foo/__init__.py", "foo/resources/js/code.js", ], expected_packages=["foo", "foo.bar", "foo.bar.baz", "foo.qux"], expected_namespace_packages=["foo.bar"], expected_package_data={"foo": ("resources/js/code.js", )}, addrs=[ Address("src/python/foo/bar/baz", target_name="baz1"), Address("src/python/foo/bar/baz", target_name="baz2"), Address("src/python/foo/qux"), Address("src/python/foo/resources"), ], )
def test_inject_python_distribution_dependencies() -> None: rule_runner = RuleRunner( rules=[ *target_types_rules.rules(), *import_rules(), *python_sources.rules(), QueryRule(InjectedDependencies, [InjectPythonDistributionDependencies]), ], target_types=[ PythonDistribution, PythonRequirementTarget, PythonSourcesGeneratorTarget, PexBinary, ], objects={"setup_py": PythonArtifact}, ) rule_runner.write_files( { "BUILD": dedent( """\ python_requirement( name='ansicolors', requirements=['ansicolors'], modules=['colors'], ) """ ), "project/app.py": "", "project/BUILD": dedent( """\ pex_binary(name="my_binary", entry_point="who_knows.module:main") python_sources(name="my_library", sources=["app.py"]) python_distribution( name="dist-a", provides=setup_py( name='my-dist-a' ), entry_points={ "console_scripts":{ "my_cmd": ":my_binary", }, }, ) python_distribution( name="dist-b", provides=setup_py( name="my-dist-b" ), entry_points={ "console_scripts":{ "b_cmd": "project.app:main", "cmd_2": "//project:my_binary", } }, ) python_distribution( name="third_dep", provides=setup_py(name="my-third"), entry_points={ "color-plugins":{ "my-ansi-colors": "colors", } } ) python_distribution( name="third_dep2", provides=setup_py( name="my-third", entry_points={ "console_scripts":{ "my-cmd": ":my_binary", "main": "project.app:main", }, "color-plugins":{ "my-ansi-colors": "colors", } } ) ) """ ), "who_knows/module.py": "", "who_knows/BUILD": dedent( """\ python_sources(name="random_lib", sources=["module.py"]) """ ), } ) def assert_injected(address: Address, expected: list[Address]) -> None: tgt = rule_runner.get_target(address) injected = rule_runner.request( InjectedDependencies, [InjectPythonDistributionDependencies(tgt[PythonDistributionDependenciesField])], ) assert injected == InjectedDependencies(expected) assert_injected( Address("project", target_name="dist-a"), [Address("project", target_name="my_binary")], ) assert_injected( Address("project", target_name="dist-b"), [ Address("project", target_name="my_binary"), Address("project", relative_file_path="app.py", target_name="my_library"), ], ) assert_injected( Address("project", target_name="third_dep"), [ Address("", target_name="ansicolors"), ], ) assert_injected( Address("project", target_name="third_dep2"), [ Address("", target_name="ansicolors"), Address("project", target_name="my_binary"), Address("project", relative_file_path="app.py", target_name="my_library"), ], )
def test_generate_source_and_test_targets() -> None: rule_runner = RuleRunner( rules=[ *target_types_rules.rules(), *import_rules(), *python_sources.rules(), QueryRule(GeneratedTargets, [GenerateTargetsFromPythonTests]), QueryRule(GeneratedTargets, [GenerateTargetsFromPythonSources]), QueryRule(GeneratedTargets, [GenerateTargetsFromPythonTestUtils]), ], target_types=[ PythonTestsGeneratorTarget, PythonSourcesGeneratorTarget, PythonTestUtilsGeneratorTarget, ], ) rule_runner.write_files({ "src/py/BUILD": dedent("""\ python_sources( name='lib', sources=['**/*.py', '!**/*_test.py', '!**/conftest.py'], overrides={'f1.py': {'tags': ['overridden']}}, ) python_tests( name='tests', sources=['**/*_test.py'], overrides={'f1_test.py': {'tags': ['overridden']}}, ) python_test_utils( name='test_utils', sources=['**/conftest.py'], overrides={'conftest.py': {'tags': ['overridden']}}, ) """), "src/py/f1.py": "", "src/py/f1_test.py": "", "src/py/conftest.py": "", "src/py/f2.py": "", "src/py/f2_test.py": "", "src/py/subdir/f.py": "", "src/py/subdir/f_test.py": "", "src/py/subdir/conftest.py": "", }) sources_generator = rule_runner.get_target( Address("src/py", target_name="lib")) tests_generator = rule_runner.get_target( Address("src/py", target_name="tests")) test_utils_generator = rule_runner.get_target( Address("src/py", target_name="test_utils")) def gen_source_tgt(rel_fp: str, tags: list[str] | None = None, *, tgt_name: str) -> PythonSourceTarget: return PythonSourceTarget( { SingleSourceField.alias: rel_fp, Tags.alias: tags }, Address("src/py", target_name=tgt_name, relative_file_path=rel_fp), residence_dir=os.path.dirname(os.path.join("src/py", rel_fp)), ) def gen_test_tgt(rel_fp: str, tags: list[str] | None = None) -> PythonTestTarget: return PythonTestTarget( { SingleSourceField.alias: rel_fp, Tags.alias: tags }, Address("src/py", target_name="tests", relative_file_path=rel_fp), residence_dir=os.path.dirname(os.path.join("src/py", rel_fp)), ) sources_generated = rule_runner.request( GeneratedTargets, [GenerateTargetsFromPythonSources(sources_generator)]) tests_generated = rule_runner.request( GeneratedTargets, [GenerateTargetsFromPythonTests(tests_generator)]) test_utils_generated = rule_runner.request( GeneratedTargets, [GenerateTargetsFromPythonTestUtils(test_utils_generator)]) assert sources_generated == GeneratedTargets( sources_generator, { gen_source_tgt("f1.py", tags=["overridden"], tgt_name="lib"), gen_source_tgt("f2.py", tgt_name="lib"), gen_source_tgt("subdir/f.py", tgt_name="lib"), }, ) assert tests_generated == GeneratedTargets( tests_generator, { gen_test_tgt("f1_test.py", tags=["overridden"]), gen_test_tgt("f2_test.py"), gen_test_tgt("subdir/f_test.py"), }, ) assert test_utils_generated == GeneratedTargets( test_utils_generator, { gen_source_tgt( "conftest.py", tags=["overridden"], tgt_name="test_utils"), gen_source_tgt("subdir/conftest.py", tgt_name="test_utils"), }, )
def test_generate_source_and_test_targets() -> None: rule_runner = RuleRunner( rules=[ *target_types_rules.rules(), *import_rules(), *python_sources.rules(), QueryRule(_TargetParametrizations, [Address]), ], target_types=[ PythonTestsGeneratorTarget, PythonSourcesGeneratorTarget, PythonTestUtilsGeneratorTarget, PexBinariesGeneratorTarget, ], ) rule_runner.write_files({ "src/py/BUILD": dedent("""\ python_sources( name='lib', sources=['**/*.py', '!**/*_test.py', '!**/conftest.py'], overrides={'f1.py': {'tags': ['overridden']}}, ) python_tests( name='tests', sources=['**/*_test.py'], overrides={'f1_test.py': {'tags': ['overridden']}}, ) python_test_utils( name='test_utils', sources=['**/conftest.py'], overrides={'conftest.py': {'tags': ['overridden']}}, ) pex_binaries( name="pexes", entry_points=[ "f1.py", "f2:foo", "subdir.f.py", "subdir.f:main", ], overrides={ 'f2:foo': {'tags': ['overridden']}, 'subdir.f.py': {'tags': ['overridden']}, } ) """), "src/py/f1.py": "", "src/py/f1_test.py": "", "src/py/conftest.py": "", "src/py/f2.py": "", "src/py/f2_test.py": "", "src/py/subdir/f.py": "", "src/py/subdir/f_test.py": "", "src/py/subdir/conftest.py": "", }) def gen_source_tgt(rel_fp: str, tags: list[str] | None = None, *, tgt_name: str) -> PythonSourceTarget: return PythonSourceTarget( { SingleSourceField.alias: rel_fp, Tags.alias: tags }, Address("src/py", target_name=tgt_name, relative_file_path=rel_fp), residence_dir=os.path.dirname(os.path.join("src/py", rel_fp)), ) def gen_test_tgt(rel_fp: str, tags: list[str] | None = None) -> PythonTestTarget: return PythonTestTarget( { SingleSourceField.alias: rel_fp, Tags.alias: tags }, Address("src/py", target_name="tests", relative_file_path=rel_fp), residence_dir=os.path.dirname(os.path.join("src/py", rel_fp)), ) def gen_pex_binary_tgt(entry_point: str, tags: list[str] | None = None) -> PexBinary: return PexBinary( { PexEntryPointField.alias: entry_point, Tags.alias: tags }, Address("src/py", target_name="pexes", generated_name=entry_point.replace(":", "-")), residence_dir="src/py", ) sources_generated = rule_runner.request( _TargetParametrizations, [Address("src/py", target_name="lib")]).parametrizations tests_generated = rule_runner.request( _TargetParametrizations, [Address("src/py", target_name="tests")]).parametrizations test_utils_generated = rule_runner.request( _TargetParametrizations, [Address("src/py", target_name="test_utils")]).parametrizations pex_binaries_generated = rule_runner.request( _TargetParametrizations, [Address("src/py", target_name="pexes")]).parametrizations assert set(sources_generated.values()) == { gen_source_tgt("f1.py", tags=["overridden"], tgt_name="lib"), gen_source_tgt("f2.py", tgt_name="lib"), gen_source_tgt("subdir/f.py", tgt_name="lib"), } assert set(tests_generated.values()) == { gen_test_tgt("f1_test.py", tags=["overridden"]), gen_test_tgt("f2_test.py"), gen_test_tgt("subdir/f_test.py"), } assert set(test_utils_generated.values()) == { gen_source_tgt("conftest.py", tags=["overridden"], tgt_name="test_utils"), gen_source_tgt("subdir/conftest.py", tgt_name="test_utils"), } assert set(pex_binaries_generated.values()) == { gen_pex_binary_tgt("f1.py"), gen_pex_binary_tgt("f2:foo", tags=["overridden"]), gen_pex_binary_tgt("subdir.f.py", tags=["overridden"]), gen_pex_binary_tgt("subdir.f:main"), }