Skip to content

Commit 0333516

Browse files
authored
Add extra data to GH section (#980)
Add `meta` in `ecosystem.json` Extend `ecosystem.json` with extra fields: Deprecate some `ecosystem.json` fields: ``` "members.created_at": "currently not in use. To be removed in v2.", "members.updated_at": "currently not in use. To be removed in v2.", "members.contact_info": "currently not in use. To be removed in v2.", "members.affiliations": "currently not in use. To be removed in v2.", "members.group": "replaced by members.category. To be removed in v2.", "members.stars": "replaced by members.github.stars. To be removed in v2.", "members.url": "replaced by members.github.url. To be removed in v2.", "members.website": "replaced by members.website.home. To be removed in v2.", ``` Support for search in json Add `github.total_dependent_repositories` and `github.total_dependent_packages`. Fetch License and description from github
1 parent f768f2a commit 0333516

File tree

109 files changed

+651
-310
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+651
-310
lines changed

ecosystem/cli/members.py

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ def update_github(self):
8888
"""Updates GitHub data."""
8989
for project in self.dao.get_all():
9090
project.update_github()
91-
self.dao.update(project.name_id, stars=project.github.stars)
9291
self.dao.update(project.name_id, github=project.github)
9392

9493
def update_pypi(self):
@@ -98,24 +97,36 @@ def update_pypi(self):
9897
self.dao.update(project.name_id, pypi=project.pypi)
9998

10099
@staticmethod
101-
def filter_member_data(member_dict, data_map):
100+
def filter_member_data(
101+
member_dict, data_map, forced_addition=False
102+
): # pylint: disable=too-many-branches
102103
"""takes a member dictionary and a data map,
103-
and returns a dict that is filtered by the map"""
104+
and returns a dict that is filtered by the map.
105+
If forced_addition is True, all the elements of the
106+
data_map will be added, even if they are empty"""
104107
filtered_data = {}
105108
for key, alias in data_map.items():
106109
if isinstance(alias, dict):
107110
data = CliMembers.filter_member_data(member_dict, alias)
108111
if data:
109112
filtered_data[key] = data
110-
elif isinstance(alias, list):
113+
elif isinstance(alias, tuple):
111114
if len(alias) != 2:
112115
raise ValueError(
113116
"%s malformed. "
114117
"It needs to have exactly two elements,one "
115118
"with the query, the otherone with the selector"
116119
)
117120
data = list(query(alias[0], member_dict).select(*alias[1]))
118-
121+
elif isinstance(alias, list):
122+
# a list of alias in priority in case they do not exist
123+
for candidate_alias in alias:
124+
candidate_value = CliMembers.filter_member_data(
125+
member_dict, {key: candidate_alias}
126+
)
127+
if len(candidate_value) == 1:
128+
data = list(candidate_value.values())[0]
129+
break
119130
else:
120131
found_all = findall(alias, member_dict)
121132
if len(found_all) == 0:
@@ -127,7 +138,7 @@ def filter_member_data(member_dict, data_map):
127138
f"I dont know who to hangle multiple results for {found_all}. "
128139
"Maybe functools.reduce?"
129140
)
130-
if data:
141+
if forced_addition or data:
131142
filtered_data[key] = data
132143
return filtered_data
133144

@@ -137,41 +148,21 @@ def compile_json(self, output_file: str):
137148
"uuid": "uuid",
138149
"name": "name",
139150
"url": "github.url",
140-
"description": "description",
141-
"licence": "licence",
151+
"description": ["description", "github.description"],
152+
"licence": ["licence", "github.license"],
142153
"contact_info": "contact_info",
143154
"affiliations": "affiliations",
144155
"labels": "labels",
145156
"created_at": "created_at",
146157
"updated_at": "updated_at",
147-
"group": "group",
158+
"group": "category",
159+
"category": "category",
148160
"stars": "github.stars",
149161
"documentation": "documentation",
150162
"website": "website",
151163
"reference_paper": "reference_paper",
152-
"ibm_maintained": "ibm_maintained",
153-
}
154-
data = {
155-
"members": [
156-
CliMembers.filter_member_data(member.to_dict(), member_data_to_export)
157-
for member in self.dao.get_all()
158-
],
159-
"labels": json.loads(Path(self.resources_dir, "labels.json").read_text()),
160-
}
161-
Path(output_file).write_text(
162-
json.dumps(data, default=str, separators=(",", ":"))
163-
)
164-
165-
def compile_json_v1(self, output_file: str):
166-
"""Compile JSON file (v1) for consumption by ibm.com"""
167-
member_data_to_export = {
168-
"name": "name",
169-
"description": "description",
170-
"licence": "licence",
171-
"subjects": "labels",
172-
"type": "group",
164+
"ibm_maintained": "ibm_maintained", # if _prefixed, then it adding it is forced
173165
"badge": "badge",
174-
"ibm_maintained": "ibm_maintained",
175166
"websites": {
176167
"home": "website",
177168
"documentation": "documentation",
@@ -183,7 +174,7 @@ def compile_json_v1(self, output_file: str):
183174
"last_commit": "github.last_commit",
184175
"archived": "github.archived",
185176
},
186-
"python_packages": [
177+
"python_packages": (
187178
"pypi.*",
188179
[
189180
"package_name",
@@ -192,11 +183,28 @@ def compile_json_v1(self, output_file: str):
192183
"compatible_with_qiskit_v1",
193184
"compatible_with_qiskit_v2",
194185
],
195-
],
186+
),
196187
}
197188
data = {
189+
"meta": {
190+
"version": 1,
191+
"deprecated fields": {
192+
"members.created_at": "currently not in use. To be removed in v2.",
193+
"members.updated_at": "currently not in use. To be removed in v2.",
194+
"members.contact_info": "currently not in use. To be removed in v2.",
195+
"members.affiliations": "currently not in use. To be removed in v2.",
196+
"members.group": "replaced by members.category. To be removed in v2.",
197+
"members.stars": "replaced by members.github.stars. To be removed in v2.",
198+
"members.url": "replaced by members.github.url. To be removed in v2.",
199+
"members.website": "replaced by members.website.home. To be removed in v2.",
200+
"reference_paper": "replaced by members.website.reference_paper. "
201+
"To be removed in v2.",
202+
},
203+
},
198204
"members": [
199-
CliMembers.filter_member_data(member.to_dict(), member_data_to_export)
205+
CliMembers.filter_member_data(
206+
member.to_dict(), member_data_to_export, forced_addition=True
207+
)
200208
for member in self.dao.get_all()
201209
],
202210
"labels": json.loads(Path(self.resources_dir, "labels.json").read_text()),

ecosystem/github.py

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from .serializable import JsonSerializable, parse_datetime
99
from .error_handling import EcosystemError, logger
10-
from .request import request_json
10+
from .request import request_json, parse_github_package_ids, parse_github_dependants
1111

1212

1313
class GitHubData(JsonSerializable):
@@ -21,18 +21,27 @@ class GitHubData(JsonSerializable):
2121
"repo",
2222
"tree",
2323
"stars",
24+
"homepage",
25+
"license",
26+
"description",
27+
"total_dependent_repositories",
28+
"total_dependent_packages",
2429
"private",
2530
"archived",
31+
"disabled",
2632
"last_commit",
2733
]
2834
aliases = {
2935
"stars": "stargazers_count",
3036
"last_commit": "pushed_at",
3137
"url": "html_url",
38+
"license": "license.name",
3239
}
3340
json_types = {
41+
"homepage": lambda x: x or None,
3442
"private": lambda x: x or None,
3543
"archived": lambda x: x or None,
44+
"disabled": lambda x: x or None,
3645
"pushed_at": parse_datetime,
3746
}
3847
reduce = {}
@@ -42,7 +51,9 @@ def __init__(self, owner: str, repo: str, tree: str = None, **kwargs):
4251
self.repo = repo
4352
self.tree = tree
4453
self._kwargs = kwargs or {}
45-
self._json_data = None
54+
self._json_repo = None
55+
self._json_package_ids = None
56+
self._json_dependants = None
4657

4758
def to_dict(self) -> dict:
4859
dictionary = {}
@@ -84,16 +95,29 @@ def from_url(cls, github_project_url: ParseResult):
8495

8596
def update_json(self):
8697
"""
87-
Fetches remote json data from api.github.com/repos/{self.owner}/{self.repo}
98+
Fetches remote data from:
99+
- api.github.com/repos/{self.owner}/{self.repo}
100+
- github.com/{self.owner}/{self.repo}/network/dependents
88101
"""
89-
self._json_data = request_json(f"api.github.com/repos/{self.owner}/{self.repo}")
102+
self._json_repo = request_json(f"api.github.com/repos/{self.owner}/{self.repo}")
103+
self._json_package_ids = request_json(
104+
f"github.com/{self.owner}/{self.repo}/network/dependents?dependent_type=REPOSITORY",
105+
parser=parse_github_package_ids,
106+
)
107+
self._json_dependants = {}
108+
for package, package_id in self._json_package_ids.items():
109+
self._json_dependants[package] = request_json(
110+
f"github.com/{self.owner}/{self.repo}/network/dependents?"
111+
f"dependent_type=REPOSITORY&package_id={package_id}",
112+
parser=parse_github_dependants,
113+
)
90114

91115
def __getattr__(self, item):
92-
if self._json_data:
116+
if self._json_repo:
93117
if item in GitHubData.aliases:
94118
item = GitHubData.aliases[item]
95119

96-
json_elements = findall(item, self._json_data)
120+
json_elements = findall(item, self._json_repo)
97121
if item in GitHubData.json_types:
98122
json_elements = [GitHubData.json_types[item](e) for e in json_elements]
99123

@@ -118,11 +142,31 @@ def update_owner_repo(self):
118142
"""
119143
Updates GitHub page when the repo was moved or renamed
120144
"""
121-
if self._json_data is None:
145+
if self._json_repo is None:
122146
self.update_json()
123-
owner = self._json_data["owner"]["login"]
124-
repo = self._json_data["name"]
147+
owner = self._json_repo["owner"]["login"]
148+
repo = self._json_repo["name"]
125149
if self.owner != owner or self.repo != repo:
126150
logger.info("%s/%s moved to %s/%s", self.owner, self.repo, owner, repo)
127151
self.owner = owner
128152
self.repo = repo
153+
154+
def dependants(self, refresh=False):
155+
"""get the dependant data from (cached) JSON"""
156+
if refresh:
157+
self.update_json()
158+
return self._json_dependants
159+
160+
@property
161+
def total_dependent_repositories(self):
162+
"""Sum of repository dependants"""
163+
if self.dependants():
164+
return sum(r.get("repositories", 0) for r in self.dependants().values())
165+
return None
166+
167+
@property
168+
def total_dependent_packages(self):
169+
"""Sum of package dependants"""
170+
if self.dependants():
171+
return sum(r.get("packages", 0) for r in self.dependants().values())
172+
return None

ecosystem/member.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ class Member(JsonSerializable):
2626
created_at: int | None = None
2727
updated_at: int | None = None
2828
website: str | None = None
29-
stars: int | None = None
3029
group: str | None = None
30+
category: str | None = None
3131
reference_paper: str | None = None
3232
documentation: str | None = None
3333
packages: list[str] | None = None
@@ -80,6 +80,8 @@ def to_dict(self) -> dict:
8080
f"%3A%2F%2Fqiskit.github.io%2Fecosystem%2Fb%2F{self.short_uuid})]"
8181
"(https://qisk.it/e)"
8282
)
83+
if "ibm_maintained" in base_dict and base_dict["ibm_maintained"] is False:
84+
del base_dict["ibm_maintained"]
8385
return base_dict
8486

8587
def __eq__(self, other: "Member"):

0 commit comments

Comments
 (0)