Skip to content

Commit

Permalink
Record metadata at install time to help pip uninstall it
Browse files Browse the repository at this point in the history
  • Loading branch information
takluyver committed Mar 17, 2015
1 parent df17f63 commit fc63963
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 18 deletions.
13 changes: 1 addition & 12 deletions flit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import pathlib
import shutil
import sys
from importlib.machinery import SourceFileLoader
import zipfile

from . import common
Expand All @@ -17,16 +16,6 @@

log = logging.getLogger(__name__)

def get_info_from_module(target):
"""Load the module/package, get its docstring and __version__
"""
sl = SourceFileLoader(target.name, str(target.file))
m = sl.load_module()
docstring_lines = m.__doc__.splitlines()
return {'summary': docstring_lines[0],
'description': '\n'.join(docstring_lines[1:]),
'version': m.__version__}

wheel_file_template = """\
Wheel-Version: 1.0
Generator: flit {version}
Expand All @@ -52,7 +41,7 @@ def wheel(target, upload=None, verify_metadata=None):

ini_info = inifile.read_pypi_ini(target.ini_file)
md_dict = {'name': target.name, 'provides': [target.name]}
md_dict.update(get_info_from_module(target))
md_dict.update(common.get_info_from_module(target))
md_dict.update(ini_info['metadata'])
metadata = common.Metadata(md_dict)

Expand Down
12 changes: 12 additions & 0 deletions flit/common.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
from importlib.machinery import SourceFileLoader

def get_info_from_module(target):
"""Load the module/package, get its docstring and __version__
"""
sl = SourceFileLoader(target.name, str(target.file))
m = sl.load_module()
docstring_lines = m.__doc__.splitlines()
return {'summary': docstring_lines[0],
'description': '\n'.join(docstring_lines[1:]),
'version': m.__version__}

script_template = """\
#!{interpreter}
from {module} import {func}
Expand Down
51 changes: 45 additions & 6 deletions flit/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,43 @@ def get_dirs(user=True):
'purelib': purelib.format_map(_interpolation_vars),
}

def install(target, user=True, symlink=False):
def record_installed_directory(path, fileslist):
site_pkgs = os.path.dirname(path)
for dirpath, dirnames, files in os.walk(path):
for f in files:
filepath = os.path.join(dirpath, f)
from_site_pkgs = os.path.relpath(filepath, site_pkgs)
# The record is from the .egg-info directory, hence the ../
fileslist.append(os.path.join('..', from_site_pkgs))

def install(mod, user=True, symlink=False):
"""Install a module/package into site-packages, and create its scripts.
"""
dirs = get_dirs(user=user)
dst = os.path.join(dirs['purelib'], target.path.name)
dst = os.path.join(dirs['purelib'], mod.path.name)
if os.path.lexists(dst):
if os.path.isdir(dst) and not os.path.islink(dst):
shutil.rmtree(dst)
else:
os.unlink(dst)

src = str(target.path)
installed_files = []

src = str(mod.path)
if symlink:
log.info("Symlinking %s -> %s", src, dst)
os.symlink(str(target.path.resolve()), dst)
elif target.path.is_dir():
os.symlink(str(mod.path.resolve()), dst)
installed_files.append(os.path.join('..', mod.path.name))
elif mod.path.is_dir():
log.info("Copying directory %s -> %s", src, dst)
shutil.copytree(src, dst)
record_installed_directory()
else:
log.info("Copying file %s -> %s", src, dst)
shutil.copy2(src, dst)
installed_files.append(os.path.join('..', mod.path.name))

scripts = read_pypi_ini(target.ini_file)['scripts']
scripts = read_pypi_ini(mod.ini_file)['scripts']

for name, (module, func) in scripts.items():
script_file = pathlib.Path(dirs['scripts']) / name
Expand All @@ -78,3 +92,28 @@ def install(target, user=True, symlink=False):
func=func
))
script_file.chmod(0o755)

from_site_pkgs = os.path.relpath(str(script_file), dirs['purelib'])
installed_files.append(os.path.join('..', from_site_pkgs))

# Record metadata about installed files to give pip a fighting chance of
# uninstalling it correctly.
module_info = common.get_info_from_module(mod)
egg_info = pathlib.Path(dirs['purelib']) / '{}-{}.egg-info'.format(
mod.name, module_info['version'])
try:
egg_info.mkdir()
except FileExistsError:
shutil.rmtree(str(egg_info))
egg_info.mkdir()
installed_files.append('./')

# Not sure what this is for, but it's easy to do, and perhaps it will
# placate the heathen gods of packaging.
with (egg_info / 'top_level.txt').open('w') as f:
f.write(mod.name)
installed_files.append('top_level.txt')

with (egg_info / 'installed-files.txt').open('w') as f:
for path in installed_files:
f.write(path + '\n')

0 comments on commit fc63963

Please sign in to comment.