pkgmap-py 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pkgmap-py
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Cross-distribution Linux package name resolution
5
5
  Author: Levizor
6
6
  Author-email: Levizor <levizor@disroot.org>
@@ -126,8 +126,8 @@ pkgmap update --full
126
126
 
127
127
  | Variant | File | Compressed Size | Coverage | Default For |
128
128
  | :--- | :--- | :--- | :--- | :--- |
129
- | **Core** | `pkgmap-core.db` | ~7 MB | Top 10 repositories (Nixpkgs, Arch, AUR, Debian, Ubuntu, Fedora, Alpine, openSUSE, Gentoo, Void) | **CLI & Web UI** |
130
- | **Full** | `pkgmap.db` | ~37 MB | All 330+ Repology repositories | **Python Library** |
129
+ | **Core** | `pkgmap-core.db` | ~12 MB | Top 10 repositories (Nixpkgs, Arch, AUR, Debian, Ubuntu, Fedora, Alpine, openSUSE, Gentoo, Void) | **CLI & Web UI** |
130
+ | **Full** | `pkgmap.db` | ~40 MB | All 330+ Repology repositories | **Python Library** |
131
131
 
132
132
  - **CLI behavior**: Defaults to the **Core** database (`~/.cache/pkgmap/pkgmap-core.db`) unless the Full database is already downloaded locally or `--full` is passed. If you query a repository not present in Core, the CLI prompts you to run `pkgmap update --full`. You can also pass `--core` or `--full` to any CLI command (`resolve`, `update`, `repos`).
133
133
  - **Python library behavior**: Defaults to the **Full** database (`~/.cache/pkgmap/pkgmap.db`). Call `set_default_variant("core")` (or set `PKGMAP_DB_VARIANT=core`) to use the Core database instead.
@@ -111,8 +111,8 @@ pkgmap update --full
111
111
 
112
112
  | Variant | File | Compressed Size | Coverage | Default For |
113
113
  | :--- | :--- | :--- | :--- | :--- |
114
- | **Core** | `pkgmap-core.db` | ~7 MB | Top 10 repositories (Nixpkgs, Arch, AUR, Debian, Ubuntu, Fedora, Alpine, openSUSE, Gentoo, Void) | **CLI & Web UI** |
115
- | **Full** | `pkgmap.db` | ~37 MB | All 330+ Repology repositories | **Python Library** |
114
+ | **Core** | `pkgmap-core.db` | ~12 MB | Top 10 repositories (Nixpkgs, Arch, AUR, Debian, Ubuntu, Fedora, Alpine, openSUSE, Gentoo, Void) | **CLI & Web UI** |
115
+ | **Full** | `pkgmap.db` | ~40 MB | All 330+ Repology repositories | **Python Library** |
116
116
 
117
117
  - **CLI behavior**: Defaults to the **Core** database (`~/.cache/pkgmap/pkgmap-core.db`) unless the Full database is already downloaded locally or `--full` is passed. If you query a repository not present in Core, the CLI prompts you to run `pkgmap update --full`. You can also pass `--core` or `--full` to any CLI command (`resolve`, `update`, `repos`).
118
118
  - **Python library behavior**: Defaults to the **Full** database (`~/.cache/pkgmap/pkgmap.db`). Call `set_default_variant("core")` (or set `PKGMAP_DB_VARIANT=core`) to use the Core database instead.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pkgmap-py"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Cross-distribution Linux package name resolution"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pkgmap-py"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Cross-distribution Linux package name resolution"
5
5
  authors = [{ name = "Levizor", email = "levizor@disroot.org" }]
6
6
  license = { text = "MIT" }
@@ -17,6 +17,7 @@ from pkgmap.resolver import (
17
17
  resolve_batch_all,
18
18
  resolve_project,
19
19
  )
20
+ from pkgmap.schema import normalize_nix_package_name
20
21
 
21
22
  __version__ = "0.2.0"
22
23
  __all__ = [
@@ -26,6 +27,7 @@ __all__ = [
26
27
  "get_database_path",
27
28
  "get_default_variant",
28
29
  "list_repositories",
30
+ "normalize_nix_package_name",
29
31
  "resolve",
30
32
  "resolve_all",
31
33
  "resolve_batch",
@@ -3,7 +3,11 @@ from collections.abc import Sequence
3
3
  from pathlib import Path
4
4
 
5
5
  from pkgmap.db import ensure_database
6
- from pkgmap.schema import PackageResolution, Repository
6
+ from pkgmap.schema import (
7
+ PackageResolution,
8
+ Repository,
9
+ normalize_nix_package_name,
10
+ )
7
11
 
8
12
  DEFAULT_ALIASES: dict[str, str] = {
9
13
  "debian": "debian_12",
@@ -96,13 +100,14 @@ BATCH_CHUNK_SIZE = 500
96
100
 
97
101
  def _rank_match(
98
102
  query_pkg: str, res: PackageResolution
99
- ) -> tuple[str, int, int, int, int, str]:
103
+ ) -> tuple[str, int, int, int, int, int, str]:
100
104
  lower_q = query_pkg.lower()
101
105
  lower_name = res.name.lower()
102
106
  return (
103
107
  res.repo,
104
108
  0 if lower_name == lower_q else 1,
105
109
  1 if lower_name.endswith(("-git", "-bin")) else 0,
110
+ 1 if "-unwrapped" in lower_name else 0,
106
111
  1 if ("." in res.name or "/" in res.name) else 0,
107
112
  len(res.name),
108
113
  res.name,
@@ -162,19 +167,30 @@ def resolve_batch_all(
162
167
  for row in cursor.fetchall():
163
168
  key = row[0]
164
169
  if key in results:
170
+ name = row[1]
171
+ repo_family = row[4]
172
+ if repo_family == "nix":
173
+ name = normalize_nix_package_name(name)
165
174
  results[key].append(
166
175
  PackageResolution(
167
- name=row[1],
176
+ name=name,
168
177
  version=row[2],
169
178
  repo=row[3],
170
- repo_family=row[4],
179
+ repo_family=repo_family,
171
180
  )
172
181
  )
173
182
 
174
183
  if src_repo:
175
184
  unmatched = [pkg for pkg in chunk if not results[pkg]]
176
185
  if unmatched:
177
- u_placeholders = ",".join("?" for _ in unmatched)
186
+ proj_to_pkgs: dict[str, list[str]] = {}
187
+ for pkg in unmatched:
188
+ proj_to_pkgs.setdefault(pkg, []).append(pkg)
189
+ norm = normalize_nix_package_name(pkg)
190
+ if norm != pkg:
191
+ proj_to_pkgs.setdefault(norm, []).append(pkg)
192
+
193
+ u_placeholders = ",".join("?" for _ in proj_to_pkgs)
178
194
  fallback_sql = f"""
179
195
  SELECT DISTINCT pr.name, dst.package_name, dst.version, dst_repo.name, dst_repo.family
180
196
  FROM projects pr
@@ -184,7 +200,7 @@ def resolve_batch_all(
184
200
  JOIN repositories dst_repo ON dst.repo_id = dst_repo.id
185
201
  WHERE src_repo.name = ? AND pr.name IN ({u_placeholders})
186
202
  """
187
- fallback_params: list[str] = [src_repo, *unmatched]
203
+ fallback_params: list[str] = [src_repo, *proj_to_pkgs.keys()]
188
204
  if dst_repo:
189
205
  fallback_sql += " AND dst_repo.name = ?"
190
206
  fallback_params.append(dst_repo)
@@ -192,22 +208,36 @@ def resolve_batch_all(
192
208
 
193
209
  cursor.execute(fallback_sql, fallback_params)
194
210
  for row in cursor.fetchall():
195
- key = row[0]
196
- if key in results:
197
- results[key].append(
198
- PackageResolution(
199
- name=row[1],
200
- version=row[2],
201
- repo=row[3],
202
- repo_family=row[4],
211
+ pr_name = row[0]
212
+ for input_key in proj_to_pkgs.get(pr_name, []):
213
+ if input_key in results:
214
+ name = row[1]
215
+ repo_family = row[4]
216
+ if repo_family == "nix":
217
+ name = normalize_nix_package_name(name)
218
+ results[input_key].append(
219
+ PackageResolution(
220
+ name=name,
221
+ version=row[2],
222
+ repo=row[3],
223
+ repo_family=repo_family,
224
+ )
203
225
  )
204
- )
205
226
 
206
227
  for pkg, matches in results.items():
207
- if len(matches) > 1:
208
- matches.sort(key=lambda r: _rank_match(pkg, r))
228
+ seen: set[tuple[str, str, str | None]] = set()
229
+ deduped: list[PackageResolution] = []
230
+ for m in matches:
231
+ dedup_key = (m.repo, m.name, m.version)
232
+ if dedup_key not in seen:
233
+ seen.add(dedup_key)
234
+ deduped.append(m)
235
+ if len(deduped) > 1:
236
+ deduped.sort(key=lambda r: _rank_match(pkg, r))
237
+ results[pkg] = deduped
209
238
 
210
239
  return results
240
+
211
241
  finally:
212
242
  conn.close()
213
243
 
@@ -1,3 +1,4 @@
1
+ import re
1
2
  from typing import NamedTuple
2
3
 
3
4
 
@@ -35,6 +36,11 @@ class PackageResolution(NamedTuple):
35
36
  REPOLOGY_SCHEMA_URL = "https://github.com/repology/repology-updater/blob/master/sql.d/schema/create_schema_tables.sql"
36
37
 
37
38
 
39
+ def normalize_nix_package_name(name: str) -> str:
40
+ """Normalize Nix package names by stripping unwrapped derivation markers."""
41
+ return re.sub(r"-unwrapped(?=($|[\"_-]))", "", name)
42
+
43
+
38
44
  class RepologyPackageRow(NamedTuple):
39
45
  """Repology 'packages' table row schema extracted from PostgreSQL dumps.
40
46
 
@@ -61,6 +67,7 @@ class RepologyPackageRow(NamedTuple):
61
67
  package_name = self.srcname
62
68
  elif self.category:
63
69
  package_name = f"{self.category}.{self.visiblename}"
70
+ package_name = normalize_nix_package_name(package_name)
64
71
 
65
72
  return PackageRecord(
66
73
  repo=self.repo,
File without changes
File without changes
File without changes