Skip to content

Commit b3e58c6

Browse files
authored
Merge pull request #47 from oeg-upm/dev
Single test functionality
2 parents 1f22a3d + e8d3dfb commit b3e58c6

13 files changed

Lines changed: 260 additions & 123 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
rsfc_env/
2+
rsfc_output/
23
build/
34
dist/
45
outputs/

CITATION.cff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ keywords:
2626
- indicators
2727
- fairness
2828
license: MIT
29-
version: 0.0.5
29+
version: 0.0.6

codemeta.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"dateCreated": "2025-07-01",
2323
"description": "Package that performs a series of checks based on a list of research software fairness indicators",
2424
"isPartOf": "https://everse.software/",
25+
"identifier": "https://doi.org/10.5281/zenodo.1653148",
2526
"keywords": [
2627
"quality",
2728
"indicators",
@@ -33,6 +34,6 @@
3334
"operatingSystem": "Linux",
3435
"programmingLanguage": "Python",
3536
"relatedLink": "https://github.com/EVERSE-ResearchSoftware/indicators",
36-
"version": "0.0.5",
37+
"version": "0.0.6",
3738
"developmentStatus": "wip"
3839
}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "rsfc"
3-
version = "0.0.5"
3+
version = "0.0.6"
44
description = "EVERSE Research Software Fairness Checks"
55
authors = ["Andres Montero <andres.montero.martin@upm.es>"]
66
license = "MIT"

run_rsfc.sh

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/bin/bash
2+
3+
if [ -z "$1" ]; then
4+
echo "Usage: $0 <repo_url> [--ftr] [--id TESTID]"
5+
exit 1
6+
fi
7+
8+
REPO_URL="$1"
9+
shift
10+
11+
FTR_FLAG=false
12+
TEST_ID=""
13+
14+
while [[ $# -gt 0 ]]; do
15+
case "$1" in
16+
--ftr)
17+
FTR_FLAG=true
18+
shift
19+
;;
20+
--id)
21+
TEST_ID="$2"
22+
shift 2
23+
;;
24+
*)
25+
echo "Unknown argument: $1"
26+
exit 1
27+
;;
28+
esac
29+
done
30+
31+
DOCKER_ARGS="--repo \"$REPO_URL\""
32+
33+
if [ "$FTR_FLAG" = true ]; then
34+
DOCKER_ARGS="$DOCKER_ARGS --ftr"
35+
fi
36+
37+
if [ -n "$TEST_ID" ]; then
38+
DOCKER_ARGS="$DOCKER_ARGS --id \"$TEST_ID\""
39+
fi
40+
41+
echo "Building rsfc-docker Docker image..."
42+
docker build -t rsfc-docker .
43+
44+
OUTPUT_DIR="rsfc_output"
45+
mkdir -p "$OUTPUT_DIR"
46+
echo "Output directory: $OUTPUT_DIR"
47+
48+
CONTAINER_ID=$(eval docker run -d rsfc-docker $DOCKER_ARGS)
49+
50+
echo "Container launched: $CONTAINER_ID"
51+
52+
docker wait "$CONTAINER_ID" > /dev/null
53+
echo "Container finished."
54+
55+
if docker cp "$CONTAINER_ID:/rsfc/outputs/rsfc_assessment.json" "$OUTPUT_DIR/rsfc_assessment.json" 2>/dev/null; then
56+
echo "File copied to: $OUTPUT_DIR/rsfc_assessment.json"
57+
else
58+
echo "the container did not generate rsfc_assessment.json"
59+
fi
60+
61+
docker rm "$CONTAINER_ID" > /dev/null
62+
echo "Container deleted."

src/rsfc/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
22

33

4-
__version__ = "0.0.5"
4+
__version__ = "0.0.6"
55

src/rsfc/harvesters/somef_harvester.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ def somef_assessment(self, repo_url, threshold):
1919

2020
repo_data = json.loads(json.dumps(repo_data.results))
2121

22-
os.makedirs('./outputs', exist_ok=True)
23-
with open('./outputs/somef_assessment.json', 'w', encoding='utf-8') as f:
24-
json.dump(repo_data, f, indent=4, ensure_ascii=False)
22+
'''os.makedirs('./rsfc_output/', exist_ok=True)
23+
with open('./rsfc_output/somef_assessment.json', 'w', encoding='utf-8') as f:
24+
json.dump(repo_data, f, indent=4, ensure_ascii=False)'''
2525

2626
return repo_data

src/rsfc/main.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ def main():
44
parser = argparse.ArgumentParser(description="RSFC - EVERSE Research Software Fairness Checks")
55
parser.add_argument("--repo", required=True, help="URL of the Github/Gitlab repository to be analyzed")
66
parser.add_argument("--ftr", action="store_true", help="Flag to indicate if JSON-LD in FTR format is desired")
7+
parser.add_argument("--id", required=False, help="Identifier of a specific test. Only that test will be ran")
78

89
args = parser.parse_args()
910

@@ -13,10 +14,15 @@ def main():
1314
import os
1415
import json
1516

16-
rsfc_asmt, table = start_assessment(args.repo, args.ftr)
17+
rsfc_asmt, table = start_assessment(args.repo, args.ftr, args.id)
18+
19+
output_dir = './rsfc_output/'
20+
output_file = "rsfc_assessment.json"
21+
output_path = os.path.join(output_dir, output_file)
1722

18-
output_path = './outputs/rsfc_assessment.json'
1923
print("Saving assessment locally...")
24+
25+
os.makedirs(output_dir, exist_ok=True)
2026

2127
if os.path.exists(output_path):
2228
os.remove(output_path)

src/rsfc/model/assessment.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,31 @@ def render_template(self, sw, ftr):
4040
return json.loads(rendered)
4141

4242

43-
def to_terminal_table(self):
43+
def to_terminal_table(self, test_id):
4444
rows = []
4545

46-
for i, check in enumerate(self.checks):
47-
desc = constants.TEST_DESC_LIST[i] if i < len(constants.TEST_DESC_LIST) else "None"
48-
49-
rows.append([
50-
check["test_id"],
51-
desc,
52-
str(check["output"])
53-
])
46+
for check in self.checks:
47+
if test_id != None:
48+
if test_id in check["test_id"]:
49+
desc = constants.TEST_DESC_DICT.get(check["test_id"], "None")
50+
51+
rows.append([
52+
check["test_id"],
53+
desc,
54+
str(check["output"])
55+
])
56+
else:
57+
desc = constants.TEST_DESC_DICT.get(check["test_id"], "None")
58+
59+
rows.append([
60+
check["test_id"],
61+
desc,
62+
str(check["output"])
63+
])
5464

5565
headers = ["TEST ID", "Short Description", "Output"]
5666
table = tabulate(rows, headers, tablefmt="grid")
5767
info = "\n\nFor rationale on the tests performed, please check the assessment file created in the outputs folder.\n"
58-
table = table +info
68+
table = table + info
5969

6070
return table

src/rsfc/model/indicator.py

Lines changed: 101 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,86 +5,141 @@ class Indicator:
55
def __init__(self, somef, cd, cf, gh):
66

77
self.test_functions = {
8-
"RSFC-01": [
9-
(rt.test_id_presence_and_resolves, [somef.somef_data]),
10-
(rt.test_id_associated_with_software, [somef.somef_data, cd.codemeta_data, cf.cff_data]),
8+
"RSFC-01-1": [
9+
(rt.test_id_presence_and_resolves, [somef.somef_data])
10+
],
11+
"RSFC-01-2": [
12+
(rt.test_id_associated_with_software, [somef.somef_data, cd.codemeta_data, cf.cff_data])
13+
],
14+
"RSFC-01-3": [
1115
(rt.test_id_common_schema, [somef.somef_data])
1216
],
13-
"RSFC-03": [
14-
(rt.test_has_releases, [somef.somef_data]),
15-
(rt.test_release_id_and_version, [somef.somef_data]),
16-
(rt.test_semantic_versioning_standard, [somef.somef_data]),
17-
(rt.test_version_scheme, [somef.somef_data]),
18-
(rt.test_latest_release_consistency, [somef.somef_data]),
17+
"RSFC-03-1": [
18+
(rt.test_has_releases, [somef.somef_data])
19+
],
20+
"RSFC-03-2": [
21+
(rt.test_release_id_and_version, [somef.somef_data])
22+
],
23+
"RSFC-03-3": [
24+
(rt.test_semantic_versioning_standard, [somef.somef_data])
25+
],
26+
"RSFC-03-4": [
27+
(rt.test_version_scheme, [somef.somef_data])
28+
],
29+
"RSFC-03-5": [
30+
(rt.test_latest_release_consistency, [somef.somef_data])
31+
],
32+
"RSFC-03-6": [
1933
(rt.test_version_number_in_metadata, [somef.somef_data, cd.codemeta_data, cf.cff_data])
2034
],
21-
"RSFC-04": [
22-
(rt.test_metadata_exists, [somef.somef_data, cd.codemeta_data, cf.cff_data]),
23-
(rt.test_readme_exists, [somef.somef_data]),
24-
(rt.test_title_description, [somef.somef_data]),
25-
(rt.test_descriptive_metadata, [somef.somef_data]),
35+
"RSFC-04-1": [
36+
(rt.test_metadata_exists, [somef.somef_data, cd.codemeta_data, cf.cff_data])
37+
],
38+
"RSFC-04-2": [
39+
(rt.test_readme_exists, [somef.somef_data])
40+
],
41+
"RSFC-04-3": [
42+
(rt.test_title_description, [somef.somef_data])
43+
],
44+
"RSFC-04-4": [
45+
(rt.test_descriptive_metadata, [somef.somef_data])
46+
],
47+
"RSFC-04-5": [
2648
(rt.test_codemeta_exists, [cd.codemeta_data])
2749
],
28-
"RSFC-05": [
29-
(rt.test_repo_status, [somef.somef_data]),
30-
(rt.test_contact_support_documentation, [somef.somef_data]),
50+
"RSFC-05-1": [
51+
(rt.test_repo_status, [somef.somef_data])
52+
],
53+
"RSFC-05-2": [
54+
(rt.test_contact_support_documentation, [somef.somef_data])
55+
],
56+
"RSFC-05-3": [
3157
(rt.test_software_documentation, [somef.somef_data])
3258
],
33-
"RSFC-06": [
34-
(rt.test_authors, [somef.somef_data, cd.codemeta_data, cf.cff_data]),
35-
(rt.test_contributors, [somef.somef_data, cd.codemeta_data]),
36-
(rt.test_authors_orcids, [cd.codemeta_data, cf.cff_data]),
59+
"RSFC-06-1": [
60+
(rt.test_authors, [somef.somef_data, cd.codemeta_data, cf.cff_data])
61+
],
62+
"RSFC-06-2": [
63+
(rt.test_contributors, [somef.somef_data, cd.codemeta_data])
64+
],
65+
"RSFC-06-3": [
66+
(rt.test_authors_orcids, [cd.codemeta_data, cf.cff_data])
67+
],
68+
"RSFC-06-4": [
3769
(rt.test_author_roles, [cd.codemeta_data])
3870
],
39-
"RSFC-07": [
40-
(rt.test_identifier_in_readme_citation, [somef.somef_data, cf.cff_data]),
71+
"RSFC-07-1": [
72+
(rt.test_identifier_in_readme_citation, [somef.somef_data, cf.cff_data])
73+
],
74+
"RSFC-07-2": [
4175
(rt.test_identifier_resolves_to_software, [somef.somef_data, cd.codemeta_data, cf.cff_data, gh.repo_url])
4276
],
43-
"RSFC-08": [
77+
"RSFC-08-1": [
4478
(rt.test_metadata_record_in_zenodo_or_software_heritage, [somef.somef_data])
4579
],
46-
"RSFC-09": [
80+
"RSFC-09-1": [
4781
(rt.test_is_github_repository, [gh.repo_url])
4882
],
49-
"RSFC-12": [
83+
"RSFC-12-1": [
5084
(rt.test_reference_publication, [somef.somef_data, cd.codemeta_data])
5185
],
52-
"RSFC-13": [
53-
(rt.test_dependencies_declared, [somef.somef_data]),
54-
(rt.test_installation_instructions, [somef.somef_data]),
55-
(rt.test_dependencies_have_version, [somef.somef_data]),
86+
"RSFC-13-1": [
87+
(rt.test_dependencies_declared, [somef.somef_data])
88+
],
89+
"RSFC-13-2": [
90+
(rt.test_installation_instructions, [somef.somef_data])
91+
],
92+
"RSFC-13-3": [
93+
(rt.test_dependencies_have_version, [somef.somef_data])
94+
],
95+
"RSFC-13-4": [
5696
(rt.test_dependencies_in_machine_readable_file, [somef.somef_data])
5797
],
58-
"RSFC-14": [
59-
(rt.test_presence_of_tests, [gh]),
98+
"RSFC-14-1": [
99+
(rt.test_presence_of_tests, [gh])
100+
],
101+
"RSFC-14-2": [
60102
(rt.test_github_action_tests, [somef.somef_data])
61103
],
62-
"RSFC-15": [
63-
(rt.test_has_license, [somef.somef_data]),
64-
(rt.test_license_spdx_compliant, [somef.somef_data]),
104+
"RSFC-15-1": [
105+
(rt.test_has_license, [somef.somef_data])
106+
],
107+
"RSFC-15-2": [
108+
(rt.test_license_spdx_compliant, [somef.somef_data])
109+
],
110+
"RSFC-15-3": [
65111
(rt.test_license_information_provided, [somef.somef_data])
66112
],
67-
"RSFC-16": [
113+
"RSFC-16-1": [
68114
(rt.test_license_info_in_metadata_files, [somef.somef_data, cd.codemeta_data, cf.cff_data])
69115
],
70-
"RSFC-17": [
71-
(rt.test_repo_enabled_and_commits, [somef.somef_data, gh]),
72-
(rt.test_commit_history, [gh]),
116+
"RSFC-17-1": [
117+
(rt.test_repo_enabled_and_commits, [somef.somef_data, gh])
118+
],
119+
"RSFC-17-2": [
120+
(rt.test_commit_history, [gh])
121+
],
122+
"RSFC-17-3": [
73123
(rt.test_commits_linked_issues, [gh])
74124
],
75-
"RSFC-18": [
125+
"RSFC-18-1": [
76126
(rt.test_has_citation, [somef.somef_data])
77127
],
78-
"RSFC-19": [
128+
"RSFC-19-1": [
79129
(rt.test_repository_workflows, [somef.somef_data])
80130
]
81131
}
82132

83-
def assess_indicators(self):
133+
def assess_indicators(self, test_id):
84134
results = []
85-
for id in self.test_functions:
86-
for func, args in self.test_functions[id]:
87-
result = func(*args)
88-
results.append(result)
135+
if test_id != None:
136+
func, args = self.test_functions[test_id][0]
137+
result = func(*args)
138+
results.append(result)
139+
else:
140+
for id in self.test_functions:
141+
for func, args in self.test_functions[id]:
142+
result = func(*args)
143+
results.append(result)
89144

90145
return results

0 commit comments

Comments
 (0)