def test_package_with_include(mocker): module_path = fixtures_dir / "with-include" # Patch git module to return specific excluded files p = mocker.patch("poetry.vcs.git.Git.get_ignored_files") p.return_value = [ str( Path(__file__).parent / "fixtures" / "with-include" / "extra_dir" / "vcs_excluded.txt"), str( Path(__file__).parent / "fixtures" / "with-include" / "extra_dir" / "sub_pkg" / "vcs_excluded.txt"), ] builder = CompleteBuilder(Factory().create_poetry(module_path), NullEnv(), NullIO()) builder.build() sdist = fixtures_dir / "with-include" / "dist" / "with-include-1.2.3.tar.gz" assert sdist.exists() with tarfile.open(str(sdist), "r") as tar: names = tar.getnames() assert len(names) == len(set(names)) assert "with-include-1.2.3/LICENSE" in names assert "with-include-1.2.3/README.rst" in names assert "with-include-1.2.3/extra_dir/__init__.py" in names assert "with-include-1.2.3/extra_dir/vcs_excluded.txt" in names assert "with-include-1.2.3/extra_dir/sub_pkg/__init__.py" in names assert "with-include-1.2.3/extra_dir/sub_pkg/vcs_excluded.txt" not in names assert "with-include-1.2.3/my_module.py" in names assert "with-include-1.2.3/notes.txt" in names assert "with-include-1.2.3/package_with_include/__init__.py" in names assert "with-include-1.2.3/tests/__init__.py" in names assert "with-include-1.2.3/pyproject.toml" in names assert "with-include-1.2.3/setup.py" in names assert "with-include-1.2.3/PKG-INFO" in names assert "with-include-1.2.3/for_wheel_only/__init__.py" not in names assert "with-include-1.2.3/src/src_package/__init__.py" in names setup = tar.extractfile("with-include-1.2.3/setup.py").read() setup_ast = ast.parse(setup) setup_ast.body = [ n for n in setup_ast.body if isinstance(n, ast.Assign) ] ns = {} exec(compile(setup_ast, filename="setup.py", mode="exec"), ns) assert ns["package_dir"] == {"": "src"} assert ns["packages"] == [ "extra_dir", "extra_dir.sub_pkg", "package_with_include", "src_package", "tests", ] assert ns["package_data"] == {"": ["*"]} assert ns["modules"] == ["my_module"] whl = module_path / "dist" / "with_include-1.2.3-py3-none-any.whl" assert whl.exists() with zipfile.ZipFile(str(whl)) as z: names = z.namelist() assert len(names) == len(set(names)) assert "with_include-1.2.3.dist-info/LICENSE" in names assert "extra_dir/__init__.py" in names assert "extra_dir/vcs_excluded.txt" in names assert "extra_dir/sub_pkg/__init__.py" in names assert "extra_dir/sub_pkg/vcs_excluded.txt" not in names assert "for_wheel_only/__init__.py" in names assert "my_module.py" in names assert "notes.txt" in names assert "package_with_include/__init__.py" in names assert "tests/__init__.py" not in names assert "src_package/__init__.py" in names
def get_shell(self): shell = Path(os.environ.get('SHELL', '')).stem if shell in ('bash', 'zsh', 'fish'): return shell
def create(cls, io, name=None, cwd=None): # type: (...) -> Venv if 'VIRTUAL_ENV' not in os.environ: # Not in a virtualenv # Checking if we need to create one # First we check if there is a .venv # at the root of the project. if cwd and (cwd / '.venv').exists(): venv = cwd / '.venv' else: config = Config.create('config.toml') create_venv = config.setting('settings.virtualenvs.create') root_venv = config.setting('settings.virtualenvs.in-project') venv_path = config.setting('settings.virtualenvs.path') if root_venv: if not cwd: raise RuntimeError('Unbale to determine the project\'s directory') venv_path = (cwd / '.venv') elif venv_path is None: venv_path = Path(CACHE_DIR) / 'virtualenvs' else: venv_path = Path(venv_path) if not name: name = Path.cwd().name name = '{}-py{}'.format( name, '.'.join([str(v) for v in sys.version_info[:2]]) ) if root_venv: venv = venv_path else: venv = venv_path / name if not venv.exists(): if create_venv is False: io.writeln( '<fg=black;bg=yellow>' 'Skipping virtualenv creation, ' 'as specified in config file.' '</>' ) return cls() io.writeln( 'Creating virtualenv <info>{}</> in {}'.format( name, str(venv_path) ) ) cls.build(str(venv)) else: if io.is_very_verbose(): io.writeln( 'Virtualenv <info>{}</> already exists.'.format(name) ) os.environ['VIRTUAL_ENV'] = str(venv) # venv detection: # stdlib venv may symlink sys.executable, so we can't use realpath. # but others can symlink *to* the venv Python, # so we can't just use sys.executable. # So we just check every item in the symlink tree (generally <= 3) p = os.path.normcase(sys.executable) paths = [p] while os.path.islink(p): p = os.path.normcase( os.path.join(os.path.dirname(p), os.readlink(p))) paths.append(p) p_venv = os.path.normcase(os.environ['VIRTUAL_ENV']) if any(p.startswith(p_venv) for p in paths): # Running properly in the virtualenv, don't need to do anything return cls() venv = os.environ['VIRTUAL_ENV'] return cls(venv)
def poetry(config): poetry = Factory().create_poetry( Path(__file__).parent.parent / "fixtures" / "simple_project") poetry.set_config(config) return poetry
def test_system_env_usersite(mocker, enabled): mocker.patch("site.check_enableusersite", return_value=enabled) env = SystemEnv(Path(sys.prefix)) assert (enabled and env.usersite is not None) or (not enabled and env.usersite is None)
def __init__( self, path, # type: Path category="main", # type: str optional=False, # type: bool base=None, # type: Path develop=True, # type: bool ): from . import dependency_from_pep_508 from .package import Package self._path = path self._base = base self._full_path = path self._develop = develop self._supports_poetry = False if self._base and not self._path.is_absolute(): self._full_path = self._base / self._path if not self._full_path.exists(): raise ValueError("Directory {} does not exist".format(self._path)) if self._full_path.is_file(): raise ValueError("{} is a file, expected a directory".format( self._path)) # Checking content to dertermine actions setup = self._full_path / "setup.py" pyproject = TomlFile(self._full_path / "pyproject.toml") if pyproject.exists(): pyproject_content = pyproject.read() self._supports_poetry = ("tool" in pyproject_content and "poetry" in pyproject_content["tool"]) if not setup.exists() and not self._supports_poetry: raise ValueError( "Directory {} does not seem to be a Python package".format( self._full_path)) if self._supports_poetry: from poetry.poetry import Poetry poetry = Poetry.create(self._full_path) package = poetry.package self._package = Package(package.pretty_name, package.version) self._package.requires += package.requires self._package.dev_requires += package.dev_requires self._package.extras = package.extras self._package.python_versions = package.python_versions else: # Execute egg_info current_dir = os.getcwd() os.chdir(str(self._full_path)) try: cwd = base venv = Env.get(NullIO(), cwd=cwd) venv.run("python", "setup.py", "egg_info") except EnvCommandError: result = SetupReader.read_from_directory(self._full_path) if not result["name"]: # The name could not be determined # so we raise an error since it is mandatory raise RuntimeError( "Unable to retrieve the package name for {}".format( path)) if not result["version"]: # The version could not be determined # so we raise an error since it is mandatory raise RuntimeError( "Unable to retrieve the package version for {}".format( path)) package_name = result["name"] package_version = result["version"] python_requires = result["python_requires"] if python_requires is None: python_requires = "*" package_summary = "" requires = "" for dep in result["install_requires"]: requires += dep + "\n" if result["extras_require"]: requires += "\n" for extra_name, deps in result["extras_require"].items(): requires += "[{}]\n".format(extra_name) for dep in deps: requires += dep + "\n" requires += "\n" reqs = parse_requires(requires) else: os.chdir(current_dir) # Sometimes pathlib will fail on recursive # symbolic links, so we need to workaround it # and use the glob module instead. # Note that this does not happen with pathlib2 # so it's safe to use it for Python < 3.4. if PY35: egg_info = next( Path(p) for p in glob.glob( os.path.join(str(self._full_path), "**", "*.egg-info"), recursive=True, )) else: egg_info = next(self._full_path.glob("**/*.egg-info")) meta = pkginfo.UnpackedSDist(str(egg_info)) package_name = meta.name package_version = meta.version package_summary = meta.summary python_requires = meta.requires_python if meta.requires_dist: reqs = list(meta.requires_dist) else: reqs = [] requires = egg_info / "requires.txt" if requires.exists(): with requires.open() as f: reqs = parse_requires(f.read()) finally: os.chdir(current_dir) package = Package(package_name, package_version) package.description = package_summary for req in reqs: package.requires.append(dependency_from_pep_508(req)) if python_requires: package.python_versions = python_requires self._package = package self._package.source_type = "directory" self._package.source_url = self._path.as_posix() super(DirectoryDependency, self).__init__( self._package.name, self._package.version, category=category, optional=optional, allows_prereleases=True, )
from poetry.repositories.installed_repository import InstalledRepository from poetry.utils._compat import Path from poetry.utils._compat import metadata from poetry.utils._compat import zipp from poetry.utils.env import MockEnv as BaseMockEnv FIXTURES_DIR = Path(__file__).parent / "fixtures" ENV_DIR = (FIXTURES_DIR / "installed").resolve() SITE_PACKAGES = ENV_DIR / "lib" / "python3.7" / "site-packages" SRC = ENV_DIR / "src" VENDOR_DIR = ENV_DIR / "vendor" / "py3.7" INSTALLED_RESULTS = [ metadata.PathDistribution(SITE_PACKAGES / "cleo-0.7.6.dist-info"), metadata.PathDistribution(SRC / "pendulum" / "pendulum.egg-info"), metadata.PathDistribution( zipp.Path(str(SITE_PACKAGES / "foo-0.1.0-py3.8.egg"), "EGG-INFO")), metadata.PathDistribution(VENDOR_DIR / "attrs-19.3.0.dist-info"), ] class MockEnv(BaseMockEnv): @property def site_packages(self): # type: () -> Path return SITE_PACKAGES def test_load(mocker): mocker.patch( "poetry.utils._compat.metadata.Distribution.discover", return_value=INSTALLED_RESULTS, )
def purelib(self): # type: () -> Path if self._purelib is None: self._purelib = Path(self.paths["purelib"]) return self._purelib
def project(name): return Path(__file__).parent / "fixtures" / name
def test_prepare_metadata_for_build_wheel(): entry_points = """\ [console_scripts] extra-script=my_package.extra:main[time] my-2nd-script=my_package:main2 my-script=my_package:main """ wheel_data = """\ Wheel-Version: 1.0 Generator: poetry {} Root-Is-Purelib: true Tag: py3-none-any """.format(__version__) metadata = """\ Metadata-Version: 2.1 Name: my-package Version: 1.2.3 Summary: Some description. Home-page: https://poetry.eustace.io/ License: MIT Keywords: packaging,dependency,poetry Author: Sébastien Eustace Author-email: [email protected] Maintainer: People Everywhere Maintainer-email: [email protected] Requires-Python: >=3.6,<4.0 Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Topic :: Software Development :: Build Tools Classifier: Topic :: Software Development :: Libraries :: Python Modules Provides-Extra: time Requires-Dist: cachy[msgpack] (>=0.2.0,<0.3.0) Requires-Dist: cleo (>=0.6,<0.7) Requires-Dist: pendulum (>=1.4,<2.0); (python_version ~= "2.7" and sys_platform == "win32" or python_version in "3.4 3.5") and (extra == "time") Project-URL: Documentation, https://poetry.eustace.io/docs Project-URL: Issue Tracker, https://github.com/sdispater/poetry/issues Project-URL: Repository, https://github.com/sdispater/poetry Description-Content-Type: text/x-rst My Package ========== """ with temporary_directory() as tmp_dir, cwd( os.path.join(fixtures, "complete")): dirname = api.prepare_metadata_for_build_wheel(tmp_dir) assert "my_package-1.2.3.dist-info" == dirname dist_info = Path(tmp_dir, dirname) assert (dist_info / "entry_points.txt").exists() assert (dist_info / "WHEEL").exists() assert (dist_info / "METADATA").exists() with (dist_info / "entry_points.txt").open(encoding="utf-8") as f: assert entry_points == decode(f.read()) with (dist_info / "WHEEL").open(encoding="utf-8") as f: assert wheel_data == decode(f.read()) with (dist_info / "METADATA").open(encoding="utf-8") as f: assert metadata == decode(f.read())