osslag 1.0.0__py3-none-any.whl → 1.0.1__py3-none-any.whl
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.
- osslag/__init__.py +9 -0
- osslag/cli.py +100 -243
- osslag/distro/debian.py +13 -41
- osslag/distro/fedora.py +1 -3
- osslag/metrics/malta.py +412 -125
- osslag/metrics/pvac.py +2 -6
- osslag/utils/github_helper.py +7 -23
- osslag/utils/vcs.py +16 -49
- {osslag-1.0.0.dist-info → osslag-1.0.1.dist-info}/METADATA +14 -8
- osslag-1.0.1.dist-info/RECORD +17 -0
- {osslag-1.0.0.dist-info → osslag-1.0.1.dist-info}/WHEEL +2 -1
- {osslag-1.0.0.dist-info → osslag-1.0.1.dist-info}/entry_points.txt +0 -1
- osslag-1.0.1.dist-info/licenses/LICENSE +21 -0
- osslag-1.0.1.dist-info/top_level.txt +1 -0
- osslag-1.0.0.dist-info/RECORD +0 -15
osslag/metrics/pvac.py
CHANGED
|
@@ -115,12 +115,8 @@ def version_delta(packages, major_weight, minor_weight, patch_weight):
|
|
|
115
115
|
if semanticA == "Unknown" or semanticB == "Unknown":
|
|
116
116
|
continue
|
|
117
117
|
|
|
118
|
-
weighted_version_A = (
|
|
119
|
-
|
|
120
|
-
)
|
|
121
|
-
weighted_version_B = (
|
|
122
|
-
(majorB * major_weight) + (minorB * minor_weight) + (patchB * patch_weight)
|
|
123
|
-
)
|
|
118
|
+
weighted_version_A = (majorA * major_weight) + (minorA * minor_weight) + (patchA * patch_weight)
|
|
119
|
+
weighted_version_B = (majorB * major_weight) + (minorB * minor_weight) + (patchB * patch_weight)
|
|
124
120
|
version_delta += abs(weighted_version_B - weighted_version_A)
|
|
125
121
|
|
|
126
122
|
return version_delta
|
osslag/utils/github_helper.py
CHANGED
|
@@ -52,11 +52,7 @@ def gh_get_rate_limit_info(github_token: str | None = None) -> dict | None:
|
|
|
52
52
|
core = rate_limit.resources.core
|
|
53
53
|
|
|
54
54
|
# core.reset is a datetime object
|
|
55
|
-
reset_dt = (
|
|
56
|
-
core.reset
|
|
57
|
-
if isinstance(core.reset, datetime)
|
|
58
|
-
else datetime.fromtimestamp(core.reset)
|
|
59
|
-
)
|
|
55
|
+
reset_dt = core.reset if isinstance(core.reset, datetime) else datetime.fromtimestamp(core.reset)
|
|
60
56
|
# convert to local timezone
|
|
61
57
|
reset_dt = reset_dt.astimezone()
|
|
62
58
|
# convert to a naive datetime in local time
|
|
@@ -164,9 +160,7 @@ def gh_check_repo_exists(owner: str, repo: str) -> GithubAPIResult:
|
|
|
164
160
|
if response.status_code == 403:
|
|
165
161
|
remaining = response.headers.get("X-RateLimit-Remaining", "?")
|
|
166
162
|
reset_time_str = response.headers.get("X-RateLimit-Reset", "")
|
|
167
|
-
error_msg = (
|
|
168
|
-
f"Rate limited (remaining: {remaining}, resets: {reset_time_str})"
|
|
169
|
-
)
|
|
163
|
+
error_msg = f"Rate limited (remaining: {remaining}, resets: {reset_time_str})"
|
|
170
164
|
return GithubAPIResult(
|
|
171
165
|
data={"owner": owner, "repo": repo},
|
|
172
166
|
error=error_msg,
|
|
@@ -182,9 +176,7 @@ def gh_check_repo_exists(owner: str, repo: str) -> GithubAPIResult:
|
|
|
182
176
|
error_msg = error_data["message"]
|
|
183
177
|
except Exception:
|
|
184
178
|
pass
|
|
185
|
-
return GithubAPIResult(
|
|
186
|
-
data={"owner": owner, "repo": repo}, error=error_msg, success=False
|
|
187
|
-
)
|
|
179
|
+
return GithubAPIResult(data={"owner": owner, "repo": repo}, error=error_msg, success=False)
|
|
188
180
|
|
|
189
181
|
# Other errors
|
|
190
182
|
error_msg = f"HTTP {response.status_code}"
|
|
@@ -195,18 +187,12 @@ def gh_check_repo_exists(owner: str, repo: str) -> GithubAPIResult:
|
|
|
195
187
|
except Exception:
|
|
196
188
|
pass
|
|
197
189
|
logger.warning(f"GitHub API error for {owner}/{repo}: {error_msg}")
|
|
198
|
-
return GithubAPIResult(
|
|
199
|
-
data={"owner": owner, "repo": repo}, error=error_msg, success=False
|
|
200
|
-
)
|
|
190
|
+
return GithubAPIResult(data={"owner": owner, "repo": repo}, error=error_msg, success=False)
|
|
201
191
|
except requests.RequestException as e:
|
|
202
|
-
return GithubAPIResult(
|
|
203
|
-
data={"owner": owner, "repo": repo}, error=str(e), success=False
|
|
204
|
-
)
|
|
192
|
+
return GithubAPIResult(data={"owner": owner, "repo": repo}, error=str(e), success=False)
|
|
205
193
|
|
|
206
194
|
|
|
207
|
-
def fetch_github_repo_metadata(
|
|
208
|
-
repo_url: str, github_token: str | None = None
|
|
209
|
-
) -> pd.DataFrame:
|
|
195
|
+
def fetch_github_repo_metadata(repo_url: str, github_token: str | None = None) -> pd.DataFrame:
|
|
210
196
|
"""Fetch GitHub repo metadata given repo URL and token.
|
|
211
197
|
|
|
212
198
|
Handles rate limiting by catching RateLimitExceededException and waiting
|
|
@@ -218,9 +204,7 @@ def fetch_github_repo_metadata(
|
|
|
218
204
|
raise ValueError(f"Invalid repository URL: {repo_url}")
|
|
219
205
|
|
|
220
206
|
# Configure GitHub client with explicit timeout (30 seconds)
|
|
221
|
-
github_client = (
|
|
222
|
-
Github(github_token, timeout=30) if github_token else Github(timeout=30)
|
|
223
|
-
)
|
|
207
|
+
github_client = Github(github_token, timeout=30) if github_token else Github(timeout=30)
|
|
224
208
|
repo_obj = github_client.get_repo(f"{owner}/{repo}")
|
|
225
209
|
data = {
|
|
226
210
|
"repo_url": repo_url,
|
osslag/utils/vcs.py
CHANGED
|
@@ -72,9 +72,7 @@ def normalize_https_repo_url(url: str) -> NormalizeRepoResult:
|
|
|
72
72
|
clean_url = f"https://github.com/{match.group(1)}/{match.group(2)}"
|
|
73
73
|
return NormalizeRepoResult(clean_url, None)
|
|
74
74
|
|
|
75
|
-
return NormalizeRepoResult(
|
|
76
|
-
None, "URL does not match expected git repository patterns"
|
|
77
|
-
)
|
|
75
|
+
return NormalizeRepoResult(None, "URL does not match expected git repository patterns")
|
|
78
76
|
|
|
79
77
|
|
|
80
78
|
def ensure_dir(p: str | os.PathLike) -> pathlib.Path:
|
|
@@ -115,9 +113,7 @@ def extract_owner_name_repo(repo_url: str) -> RepoOwnerName:
|
|
|
115
113
|
if repo_url_normalized and repo_url_normalized.url is not None:
|
|
116
114
|
parts = repo_url_normalized.url.split("/")
|
|
117
115
|
if len(parts) < 2:
|
|
118
|
-
logger.error(
|
|
119
|
-
"Could not extract owner/repo from URL: call normalize_repo_url first"
|
|
120
|
-
)
|
|
116
|
+
logger.error("Could not extract owner/repo from URL: call normalize_repo_url first")
|
|
121
117
|
return RepoOwnerName(None, None)
|
|
122
118
|
owner = parts[-2]
|
|
123
119
|
repo = parts[-1]
|
|
@@ -206,15 +202,11 @@ def clone_repo(
|
|
|
206
202
|
github_token = os.getenv("GITHUB_TOKEN")
|
|
207
203
|
github_username = os.getenv("GITHUB_USERNAME")
|
|
208
204
|
if github_token and github_username:
|
|
209
|
-
callbacks = pygit2.RemoteCallbacks(
|
|
210
|
-
pygit2.UserPass(github_username, github_token)
|
|
211
|
-
)
|
|
205
|
+
callbacks = pygit2.RemoteCallbacks(pygit2.UserPass(github_username, github_token))
|
|
212
206
|
else:
|
|
213
207
|
callbacks = None
|
|
214
208
|
|
|
215
|
-
repo_obj = pygit2.clone_repository(
|
|
216
|
-
sanitize_url.url, dest_dir, callbacks=callbacks, bare=False
|
|
217
|
-
)
|
|
209
|
+
repo_obj = pygit2.clone_repository(sanitize_url.url, dest_dir, callbacks=callbacks, bare=False)
|
|
218
210
|
|
|
219
211
|
# Checkout specific branch if requested
|
|
220
212
|
if branch:
|
|
@@ -274,9 +266,7 @@ def construct_repo_local_path(
|
|
|
274
266
|
Examples:
|
|
275
267
|
>>> construct_repo_local_path("https://github.com/owner/repo", "./cache")
|
|
276
268
|
None # if not cloned yet
|
|
277
|
-
>>> construct_repo_local_path(
|
|
278
|
-
... "https://github.com/owner/repo", "./cache", must_exist=False
|
|
279
|
-
... )
|
|
269
|
+
>>> construct_repo_local_path("https://github.com/owner/repo", "./cache", must_exist=False)
|
|
280
270
|
PosixPath('./cache/owner--repo')
|
|
281
271
|
|
|
282
272
|
"""
|
|
@@ -289,9 +279,7 @@ def construct_repo_local_path(
|
|
|
289
279
|
return None
|
|
290
280
|
|
|
291
281
|
REPOS_CACHE_DIR = os.getenv("REPOS_CACHE_DIR") or str(cache_dir)
|
|
292
|
-
local_repo_path = (
|
|
293
|
-
pathlib.Path(REPOS_CACHE_DIR) / f"{repo_owner.owner}--{repo_owner.name}"
|
|
294
|
-
)
|
|
282
|
+
local_repo_path = pathlib.Path(REPOS_CACHE_DIR) / f"{repo_owner.owner}--{repo_owner.name}"
|
|
295
283
|
if must_exist and not local_repo_path.exists():
|
|
296
284
|
return None
|
|
297
285
|
if local_repo_path.exists():
|
|
@@ -332,10 +320,7 @@ def label_trivial_commits(
|
|
|
332
320
|
return True
|
|
333
321
|
|
|
334
322
|
# Documentation-only change if all files are .md files
|
|
335
|
-
rval = all(
|
|
336
|
-
isinstance(f, str) and pathlib.PurePosixPath(f).suffix.lower() == ".md"
|
|
337
|
-
for f in files
|
|
338
|
-
)
|
|
323
|
+
rval = all(isinstance(f, str) and pathlib.PurePosixPath(f).suffix.lower() == ".md" for f in files)
|
|
339
324
|
return rval
|
|
340
325
|
|
|
341
326
|
commits_df[label_column] = commits_df[files_column].apply(_is_trivial)
|
|
@@ -388,9 +373,7 @@ def load_commits(
|
|
|
388
373
|
|
|
389
374
|
git_dir = repo_path / ".git"
|
|
390
375
|
if not git_dir.exists():
|
|
391
|
-
raise FileNotFoundError(
|
|
392
|
-
f"Not a Git repository (missing .git directory): {repo_path}"
|
|
393
|
-
)
|
|
376
|
+
raise FileNotFoundError(f"Not a Git repository (missing .git directory): {repo_path}")
|
|
394
377
|
|
|
395
378
|
try:
|
|
396
379
|
repo = pygit2.Repository(str(repo_path))
|
|
@@ -406,16 +389,12 @@ def load_commits(
|
|
|
406
389
|
ref = repo.references[f"refs/remotes/origin/{branch}"]
|
|
407
390
|
start_id = ref.peel(pygit2.Commit).id
|
|
408
391
|
except KeyError as e:
|
|
409
|
-
raise ValueError(
|
|
410
|
-
f"Branch '{branch}' not found in {repo_path}"
|
|
411
|
-
) from e
|
|
392
|
+
raise ValueError(f"Branch '{branch}' not found in {repo_path}") from e
|
|
412
393
|
else:
|
|
413
394
|
try:
|
|
414
395
|
start_id = repo.head.peel(pygit2.Commit).id
|
|
415
396
|
except pygit2.GitError as e:
|
|
416
|
-
raise ValueError(
|
|
417
|
-
f"Repository has no HEAD (empty repository?): {repo_path}"
|
|
418
|
-
) from e
|
|
397
|
+
raise ValueError(f"Repository has no HEAD (empty repository?): {repo_path}") from e
|
|
419
398
|
|
|
420
399
|
def _changed_paths(c: pygit2.Commit) -> list[str]:
|
|
421
400
|
"""Return list of paths touched by the commit (optimized, skips merge commits)."""
|
|
@@ -431,18 +410,14 @@ def load_commits(
|
|
|
431
410
|
if c.parents:
|
|
432
411
|
# Diff from parent to commit (shows what changed in this commit)
|
|
433
412
|
# context_lines=0 skips computing context around changes
|
|
434
|
-
diff = c.parents[0].tree.diff_to_tree(
|
|
435
|
-
c.tree, flags=flags, context_lines=0
|
|
436
|
-
)
|
|
413
|
+
diff = c.parents[0].tree.diff_to_tree(c.tree, flags=flags, context_lines=0)
|
|
437
414
|
else:
|
|
438
415
|
# Initial commit - diff against empty tree
|
|
439
416
|
diff = c.tree.diff_to_tree(flags=flags, context_lines=0)
|
|
440
417
|
|
|
441
418
|
# Extract paths directly with list comprehension
|
|
442
419
|
# new_file.path is set for adds/modifies, old_file.path for deletes
|
|
443
|
-
return [
|
|
444
|
-
delta.new_file.path or delta.old_file.path for delta in diff.deltas
|
|
445
|
-
]
|
|
420
|
+
return [delta.new_file.path or delta.old_file.path for delta in diff.deltas]
|
|
446
421
|
except Exception:
|
|
447
422
|
return []
|
|
448
423
|
|
|
@@ -480,12 +455,8 @@ def load_commits(
|
|
|
480
455
|
continue
|
|
481
456
|
row = {
|
|
482
457
|
"hash": str(commit.id),
|
|
483
|
-
"author": _safe_str(
|
|
484
|
-
|
|
485
|
-
),
|
|
486
|
-
"email": _safe_str(
|
|
487
|
-
lambda c=commit: c.author.email if c.author else None
|
|
488
|
-
),
|
|
458
|
+
"author": _safe_str(lambda c=commit: c.author.name if c.author else None),
|
|
459
|
+
"email": _safe_str(lambda c=commit: c.author.email if c.author else None),
|
|
489
460
|
"message": _safe_str(lambda c=commit: c.message),
|
|
490
461
|
"timestamp": commit.commit_time,
|
|
491
462
|
"date": datetime.fromtimestamp(commit.commit_time),
|
|
@@ -524,12 +495,8 @@ def find_upstream_version_tag_commit(
|
|
|
524
495
|
version_tag_patterns = [
|
|
525
496
|
re.compile(rf"^v{re.escape(version)}$"), # v1.2.3
|
|
526
497
|
re.compile(rf"^{re.escape(version)}$"), # 1.2.3
|
|
527
|
-
re.compile(
|
|
528
|
-
|
|
529
|
-
), # release-1.2.3 or release_1.2.3
|
|
530
|
-
re.compile(
|
|
531
|
-
rf"^version[-_]?{re.escape(version)}$"
|
|
532
|
-
), # version-1.2.3 or version_1.2.3
|
|
498
|
+
re.compile(rf"^release[-_]?{re.escape(version)}$"), # release-1.2.3 or release_1.2.3
|
|
499
|
+
re.compile(rf"^version[-_]?{re.escape(version)}$"), # version-1.2.3 or version_1.2.3
|
|
533
500
|
]
|
|
534
501
|
|
|
535
502
|
for _, row in commits.iterrows():
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: osslag
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Technical Lag tools for Open Source Software Projects
|
|
5
|
-
Keywords: oss,open source,technical lag,software lag,software maintenance
|
|
6
|
-
Author: Shane Panter
|
|
7
5
|
Author-email: Shane Panter <shanepanter@boisestate.edu>
|
|
8
6
|
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/shanep/osslag
|
|
8
|
+
Project-URL: Issues, https://github.com/shanep/osslag/issues
|
|
9
|
+
Keywords: oss,open source,technical lag,software lag,software maintenance
|
|
9
10
|
Classifier: Intended Audience :: Science/Research
|
|
10
11
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
12
|
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Requires-Python: >=3.14
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
12
16
|
Requires-Dist: dotenv>=0.9.9
|
|
13
17
|
Requires-Dist: pandas>=3.0.0
|
|
18
|
+
Requires-Dist: pyarrow>=23.0.0
|
|
14
19
|
Requires-Dist: pygit2>=1.19.1
|
|
15
20
|
Requires-Dist: pygithub>=2.8.1
|
|
16
21
|
Requires-Dist: python-dateutil>=2.9.0.post0
|
|
@@ -18,16 +23,17 @@ Requires-Dist: python-debian>=1.0.1
|
|
|
18
23
|
Requires-Dist: requests>=2.32.5
|
|
19
24
|
Requires-Dist: rich>=14.3.1
|
|
20
25
|
Requires-Dist: typer>=0.21.1
|
|
21
|
-
|
|
22
|
-
Project-URL: Homepage, https://github.com/shanep/osslag
|
|
23
|
-
Project-URL: Issues, https://github.com/shanep/osslag/issues
|
|
24
|
-
Description-Content-Type: text/markdown
|
|
26
|
+
Dynamic: license-file
|
|
25
27
|
|
|
26
28
|
# OSS-Lag: Open Source Software Lag Dataset
|
|
27
29
|
|
|
28
30
|
This repository contains code to build a dataset measuring technical lag and
|
|
29
31
|
abandonment of open source packages across multiple Linux distributions.
|
|
30
32
|
|
|
33
|
+
The algorithms implemented here are described in the following paper:
|
|
34
|
+
|
|
35
|
+
- [docs/Paper.pdf](docs/Paper.pdf)
|
|
36
|
+
|
|
31
37
|
|
|
32
38
|
## Installation
|
|
33
39
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
osslag/__init__.py,sha256=cwlK7jN7SyU_ao6nLWTJxjOX-5WzTEdZJrcwrTnRgeI,212
|
|
2
|
+
osslag/cli.py,sha256=IswvyAStwEUt8VRhCelULd51UAViwsD7klwDOi8P6eM,51110
|
|
3
|
+
osslag/distro/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
osslag/distro/debian.py,sha256=iCItgoK4H59fbBl-wB4MYREiHKziN3LrGP8PMATyveY,12561
|
|
5
|
+
osslag/distro/fedora.py,sha256=kJwwGSr6Sw2lZW82gnzEUYHog9lrKJCy3Johu9ZjC2M,1168
|
|
6
|
+
osslag/metrics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
osslag/metrics/malta.py,sha256=aElue_1_NWcWzSdCffI2bhe13mPsRCKXVgjVnJx4r-o,30668
|
|
8
|
+
osslag/metrics/pvac.py,sha256=L04fKxKAgWDB-mPUwNQCwp7R6UiaPSSKgiPiGVmV35o,6088
|
|
9
|
+
osslag/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
osslag/utils/github_helper.py,sha256=MU40G0EjRTGBenQTFpQm_nUL5rvBKvYp7mEIiafWhsE,8576
|
|
11
|
+
osslag/utils/vcs.py,sha256=m8U4is6k5uXsLr-KRzcVrb2tWJ2bDsbi44iXkB9QTIc,18717
|
|
12
|
+
osslag-1.0.1.dist-info/licenses/LICENSE,sha256=ohKRn422C1u0QfHnJgBh_YHgTfLySo4ncRuw_T32yzE,1072
|
|
13
|
+
osslag-1.0.1.dist-info/METADATA,sha256=Ur48ahgiXroiBOvVde-Ttkqdnqu3Qotouy-mu_IPAqI,1451
|
|
14
|
+
osslag-1.0.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
15
|
+
osslag-1.0.1.dist-info/entry_points.txt,sha256=LfxP6PyXpMTwnuATQp2hZ0iIOOAXarQlz0pMIQU-NRU,43
|
|
16
|
+
osslag-1.0.1.dist-info/top_level.txt,sha256=5RYA9YhTanChK5jQFElHU_4kMqiqWkZXyCEpRmtvIyk,7
|
|
17
|
+
osslag-1.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shane K. Panter
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
osslag
|
osslag-1.0.0.dist-info/RECORD
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
osslag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
osslag/cli.py,sha256=APVFUBACfJ-PRs9pwvD359aaCRd4w6KCZcAjGdTWNoM,52658
|
|
3
|
-
osslag/distro/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
osslag/distro/debian.py,sha256=sjodEtq8rboTkWfywn3wrbC-RiDmIURev7XvB9KJ_Ig,12867
|
|
5
|
-
osslag/distro/fedora.py,sha256=88b9gIMUaixCwsjQpX5oBK654tFLVI_8Bv3QwwdV3Yo,1174
|
|
6
|
-
osslag/metrics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
osslag/metrics/malta.py,sha256=ToT4imGHXHkws-y9m9qUMn913OMakRF1qPMiXR-wGEI,19563
|
|
8
|
-
osslag/metrics/pvac.py,sha256=tfkMbYFS6Mk-pEocu6sMOIoniD5to0QA-p8OyXW2lyo,6136
|
|
9
|
-
osslag/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
osslag/utils/github_helper.py,sha256=vsWPoSqKEcNaa_1MdUJlWJhP4CCwW-Es4CyodOr7tUs,8752
|
|
11
|
-
osslag/utils/vcs.py,sha256=EMtHgZ6ftQVn-B9H0D6gUhWK-YjGBp05ArAymcH7V4w,19203
|
|
12
|
-
osslag-1.0.0.dist-info/WHEEL,sha256=fAguSjoiATBe7TNBkJwOjyL1Tt4wwiaQGtNtjRPNMQA,80
|
|
13
|
-
osslag-1.0.0.dist-info/entry_points.txt,sha256=-MrR4OE3-FnFkYTVyMYLbhwzpLBKgTtrDvCyvHUQqP8,44
|
|
14
|
-
osslag-1.0.0.dist-info/METADATA,sha256=o1c5-RahYQoECta_PLJlukYme-azqzKTuikE4DlJ5z8,1290
|
|
15
|
-
osslag-1.0.0.dist-info/RECORD,,
|