Skip to content

Commit

Permalink
Remove pip subprocesses, replace with unearth
Browse files Browse the repository at this point in the history
  • Loading branch information
wimglenn committed Oct 22, 2024
1 parent c46bc74 commit aa2d7a4
Show file tree
Hide file tree
Showing 22 changed files with 675 additions and 898 deletions.
8 changes: 0 additions & 8 deletions .coveragerc

This file was deleted.

10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
groups:
actions-infrastructure:
patterns:
- actions/*
19 changes: 10 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: CI

on:
push:
branches: ["main"]
branches: [main]
pull_request:
branches: ["main"]
branches: [main]
workflow_dispatch:

jobs:
Expand All @@ -13,28 +13,29 @@ jobs:
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"

steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -VV
python -m pip install -r requirements-dev.txt
run: pip install -r requirements-dev.txt

- name: Run tests for ${{ matrix.python-version }} on ${{ matrix.os }}
run: python -m pytest
run: pytest

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
11 changes: 10 additions & 1 deletion johnnydep/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
"""Display dependency tree of Python distribution"""
from johnnydep.lib import *
from types import SimpleNamespace


config = SimpleNamespace(
env=None,
index_url=None,
extra_index_url=None,
)

from .lib import *
4 changes: 0 additions & 4 deletions johnnydep/__main__.py

This file was deleted.

21 changes: 10 additions & 11 deletions johnnydep/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
from importlib.metadata import version

import johnnydep
from johnnydep.lib import has_error
from johnnydep.lib import JohnnyDist
from johnnydep.logs import configure_logging
from johnnydep.util import python_interpreter
from . import config
from .lib import has_error
from .lib import JohnnyDist
from .logs import configure_logging
from .util import python_interpreter


FIELDS = {
Expand Down Expand Up @@ -120,13 +121,11 @@ def main(argv=None, stdout=None):
if "ALL" in args.fields:
args.fields = list(FIELDS)
configure_logging(verbosity=args.verbose)
dist = JohnnyDist(
args.req,
index_url=args.index_url,
env=args.env,
extra_index_url=args.extra_index_url,
ignore_errors=args.ignore_errors,
)
config.index_url = args.index_url
config.extra_index_url = args.extra_index_url
if args.env is not None:
config.env = args.env
dist = JohnnyDist(args.req, ignore_errors=args.ignore_errors)
rendered = dist.serialise(
fields=args.fields,
format=args.output_format,
Expand Down
12 changes: 6 additions & 6 deletions johnnydep/dot.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from importlib.metadata import version

from anytree import LevelOrderIter

from johnnydep.util import CircularMarker
from .util import _bfs
from .util import CircularMarker


template = """\
Expand All @@ -26,13 +25,14 @@ def jd2dot(dist, comment=None):
comment = "# " + comment
title = dist.project_name.replace("-", "_")
edges = []
for node in LevelOrderIter(dist):
for node in _bfs(dist):
if isinstance(node, CircularMarker):
# todo - render cycles differently?
continue
if node.parent is not None:
if node.parents:
[parent] = node.parents
node_name = node._name_with_extras(attr="project_name")
parent_node_name = node.parent._name_with_extras(attr="project_name")
parent_node_name = parent._name_with_extras(attr="project_name")
spec = node.req.specifier
label = f' [label="{spec}"]' if spec else ""
edge = f'"{parent_node_name}" -> "{node_name}"'
Expand Down
41 changes: 41 additions & 0 deletions johnnydep/downloader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from urllib.parse import urlparse
from urllib.request import build_opener
from urllib.request import HTTPBasicAuthHandler
from urllib.request import HTTPPasswordMgrWithDefaultRealm

from structlog import get_logger


log = get_logger(__name__)


def _urlretrieve(url, f, data=None, auth=None):
if auth is None:
opener = build_opener()
else:
# https://docs.python.org/3/howto/urllib2.html#id5
password_mgr = HTTPPasswordMgrWithDefaultRealm()
username, password = auth
top_level_url = urlparse(url).netloc
password_mgr.add_password(None, top_level_url, username, password)
handler = HTTPBasicAuthHandler(password_mgr)
opener = build_opener(handler)
res = opener.open(url, data=data)
log.debug("resp info", url=url, headers=res.info())
f.write(res.read())
f.flush()


def download_dist(url, f, index_url, extra_index_url):
auth = None
if index_url:
parsed = urlparse(index_url)
if parsed.username and parsed.password and parsed.hostname == urlparse(url).hostname:
# handling private PyPI credentials in index_url
auth = (parsed.username, parsed.password)
if extra_index_url:
parsed = urlparse(extra_index_url)
if parsed.username and parsed.password and parsed.hostname == urlparse(url).hostname:
# handling private PyPI credentials in extra_index_url
auth = (parsed.username, parsed.password)
_urlretrieve(url, f, auth=auth)
44 changes: 12 additions & 32 deletions johnnydep/env_check.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,22 @@
import json
import os
import platform
import sys


def format_full_version(info):
version = "{0.major}.{0.minor}.{0.micro}".format(info)
kind = info.releaselevel
if kind != "final":
version += kind[0] + str(info.serial)
return version


# cribbed from packaging.markers to avoid a runtime dependency here
def default_environment():
iver = format_full_version(sys.implementation.version)
implementation_name = sys.implementation.name
return {
"implementation_name": implementation_name,
"implementation_version": iver,
"os_name": os.name,
"platform_machine": platform.machine(),
"platform_release": platform.release(),
"platform_system": platform.system(),
"platform_version": platform.version(),
"python_full_version": platform.python_version(),
"platform_python_implementation": platform.python_implementation(),
"python_version": ".".join(platform.python_version_tuple()[:2]),
"sys_platform": sys.platform,
}
from packaging.markers import default_environment
from packaging.tags import interpreter_name
from unearth.pep425tags import get_supported


def main():
env = default_environment()
env = {}
env.update(default_environment())
env["python_executable"] = sys.executable
env = sorted(env.items())
result = json.dumps(env, indent=2)
print(result)
env["py_ver"] = sys.version_info[0], sys.version_info[1]
env["impl"] = interpreter_name()
env["platforms"] = None
env["abis"] = None
env["supported_tags"] = ",".join(map(str, get_supported()))
txt = json.dumps(env, indent=2, sort_keys=True)
print(txt)


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit aa2d7a4

Please sign in to comment.