Skip to content

Commit

Permalink
Map selected dependencies to their official pypi name
Browse files Browse the repository at this point in the history
This commit...

1. ensures backward compatibility for packages, requesting dependencies with
   their legacy name, by mapping them to official PyPI names.
    
   This is required to be able to install those packages from official wheels.

2. ensures forward compatibility of information from channel_v3 or repositories,
   by translating dependency names to official PyPI names, also.

   This is required to keep working until proper channel_v4 data are available
   for all users.
  • Loading branch information
deathaxe committed Oct 14, 2023
1 parent 9ea8371 commit bb8327a
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
33 changes: 33 additions & 0 deletions package_control/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,36 @@
from . import distinfo
from .clear_directory import delete_directory

# Most legacy dependency are simply re-packed python packages.
# Some of them had been given different names, which would cause issues, when
# installing them directly from pypi.org. They are therefore translated, using
# the following name map. This way legacy and maybe unmaintained packages
# which still request old dependencies are pointed to the new ones,
# which should reduce friction when moving on to python 3.8 onwards.
DEPENDENCY_NAME_MAP = {
"bs4": "beautifulsoup4",
"python-docx": "docx",
"python-jinja2": "Jinja2",
"python-markdown": "Markdown",
"python-pywin32": "pywin32",
"python-six": "six",
"python-toml": "toml",
"ruamel-yaml": "ruamel.yaml",
}


def translate_name(dependency_name):
"""
Translate old dependency name to real pypi library name
:param dependency_name:
Legacy Sublime Text dependency name
:returns:
PyPI complient library name.
"""
return DEPENDENCY_NAME_MAP.get(dependency_name, dependency_name)


class Library:
__slots__ = ['name', 'python_version']
Expand Down Expand Up @@ -166,6 +196,9 @@ def convert_dependency(dependency_path, python_version, name, version, descripti
An optional unicode string of the homepage for the library
"""

# convert legacy dependency names to official pypi package names
name = translate_name(name)

py = python_version.replace(".", "")
plat = sublime.platform()
arch = sublime.arch()
Expand Down
15 changes: 14 additions & 1 deletion package_control/package_cleanup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import time
import traceback

from . import sys_path, text, __version__
from . import library, sys_path, text, __version__
from .activity_indicator import ActivityIndicator
from .automatic_upgrader import AutomaticUpgrader
from .clear_directory import clear_directory, delete_directory
Expand Down Expand Up @@ -96,6 +96,8 @@ def run(self):
orphaned_ignored_packages = None
removed_packages = None

self.remove_legacy_libraries()

# Check metadata to verify packages were not improperly installed
self.migrate_incompatible_packages(found_packages)

Expand Down Expand Up @@ -459,6 +461,17 @@ def install_missing_packages(self, found_packages):
'\n- '.join(missing_packages)
)

def remove_legacy_libraries(self):
"""
Rename .dist-info directory
Prevent corruptions when satisfying libraries due to name translations
"""

for lib in library.list_all():
if lib.name in library.DEPENDENCY_NAME_MAP:
library.remove(lib)

def remove_orphaned_packages(self, found_packages):
"""
Removes orphaned packages.
Expand Down
16 changes: 13 additions & 3 deletions package_control/package_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def get_libraries(self, package_name):
if not names:
return set()

return set(library.Library(name, python_version) for name in names)
return set(library.Library(library.translate_name(name), python_version) for name in names)

def get_python_version(self, package_name):
"""
Expand Down Expand Up @@ -523,6 +523,11 @@ def list_repositories(self):
try:
filtered_libraries = {}
for name, info in provider.get_libraries(repo):
# Convert legacy dependency names to official pypi package names.
# This is required for forward compatibility with upcomming changes
# in scheme 4.0.0. Do it here to apply only on client side.
name = info['name'] = library.translate_name(name)

info['releases'] = self.select_releases(name, info['releases'])
if info['releases']:
filtered_libraries[name] = info
Expand Down Expand Up @@ -652,6 +657,11 @@ def download_repo(url):
repository_libraries = {}
unavailable_libraries = []
for name, info in provider.get_libraries():
# Convert legacy dependency names to official pypi package names.
# This is required for forward compatibility with upcomming changes
# in scheme 4.0.0. Do it here to apply only on client side.
name = info['name'] = library.translate_name(name)

info['releases'] = self.select_releases(name, info['releases'])
if info['releases']:
repository_libraries[name] = info
Expand Down Expand Up @@ -1221,7 +1231,7 @@ def install_library(self, lib):

if library_names:
self.install_libraries(
(library.Library(name, lib.python_version) for name in library_names),
(library.Library(library.translate_name(name), lib.python_version) for name in library_names),
fail_early=False
)

Expand Down Expand Up @@ -1558,7 +1568,7 @@ def install_package(self, package_name, unattended=False):

if library_names:
self.install_libraries(
(library.Library(name, python_version) for name in library_names),
(library.Library(library.translate_name(name), python_version) for name in library_names),
fail_early=False
)

Expand Down

0 comments on commit bb8327a

Please sign in to comment.