Skip to content

Commit cbda849

Browse files
committed
Merge branch 'cookiecutterinstall' into 25-check-if-we-need-to-upgrade-to-python-313-and-validate-compatibility-pybis-custom-parsers-etc-if-compatibility-issues-arise-keep-python312-lucaszimm
2 parents f71698c + 2370b88 commit cbda849

17 files changed

Lines changed: 117 additions & 89 deletions

File tree

.github/workflows/actions.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ jobs:
3737
python -m mypy --ignore-missing-imports --follow-imports=silent --no-strict-optional openbis_upload_helper tests
3838
- name: Test with pytest
3939
run: |
40-
python -m pytest -sv tests
40+
python -m pip install pytest-django
41+
python -m pytest -sv tests --reuse-db
4142
- name: Ruff linting
4243
run: |
44+
pip install ruff
4345
ruff check .
4446
- name: Ruff formatting
4547
run: |

config/settings/base.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,18 @@
326326
SOCIALACCOUNT_ADAPTER = "openbis_upload_helper.users.adapters.SocialAccountAdapter"
327327
# https://docs.allauth.org/en/latest/socialaccount/configuration.html
328328
SOCIALACCOUNT_FORMS = {
329-
"signup": "openbis_upload_helper.users.forms.UserSocialSignupForm"
329+
"signup": "openbis_upload_helper.users.forms.UserSocialSignupForm",
330330
}
331331

332332

333333
# Your stuff...
334334
# ------------------------------------------------------------------------------
335+
# [openbis]
336+
SECRET_ENCRYPTION_KEY = env(
337+
"DJANGO_SECRET_KEY",
338+
default="QZedkfcMcVvpwwrGieUCQdPmsHaz1ZwHwSSQZnKyq9sb4ZcKzjEEa4XRUnQ1ZYk0",
339+
)
340+
OPENBIS_URL = env(
341+
"OPENBIS_URL",
342+
default="https://openbis.example.org",
343+
)

config/settings/local.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
# ------------------------------------------------------------------------------
3030
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
3131
EMAIL_BACKEND = env(
32-
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend",
32+
"DJANGO_EMAIL_BACKEND",
33+
default="django.core.mail.backends.console.EmailBackend",
3334
)
3435

3536
# WhiteNoise

openbis_upload_helper/app/admin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
from django.contrib import admin
1+
# for future use from django.contrib import admin
22

33
# Register your models here.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
from django.db import models
1+
# for future use from django.db import models
22

33
# Create your models here.

openbis_upload_helper/app/tests.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
11
from django.test import TestCase
22

33
# Create your tests here.
4+
5+
6+
def test_placeholder():
7+
assert True
8+
9+
10+
class TestCaseClass(TestCase):
11+
def test_example(self):
12+
var_two = 2
13+
assert var_two == 1 + 1
Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
from .utils import (
2-
FileLoader,
3-
FileRemover,
4-
FilesParser,
5-
decrypt_password,
6-
encrypt_password,
7-
extract_name,
8-
get_openbis_from_cache,
9-
log_results,
10-
preload_context_request,
11-
reorganize_spaces,
12-
)
1+
from .utils import FileLoader as FileLoader
2+
from .utils import FileRemover as FileRemover
3+
from .utils import FilesParser as FilesParser
4+
from .utils import decrypt_password as decrypt_password
5+
from .utils import encrypt_password as encrypt_password
6+
from .utils import extract_name as extract_name
7+
from .utils import get_openbis_from_cache as get_openbis_from_cache
8+
from .utils import log_results as log_results
9+
from .utils import preload_context_request as preload_context_request
10+
from .utils import reorganize_spaces as reorganize_spaces

openbis_upload_helper/app/utils/utils.py

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import datetime
2-
import os
32
import re
43
import shutil
54
import tarfile
65
import tempfile
76
import time
87
import uuid
98
import zipfile
9+
from pathlib import Path
1010

1111
from bam_masterdata.logger import log_storage
1212
from bam_masterdata.logger import logger
@@ -36,10 +36,11 @@ def decrypt_password(encrypted_password):
3636
return decrypted_password.decode("utf-8")
3737
except InvalidToken as e:
3838
logger.error(f"Decryption failed: {e!s}")
39-
raise InvalidToken("Decryption failed due to an invalid token.")
39+
msg = "Decryption failed due to an invalid token."
40+
raise InvalidToken(msg) from e
4041
except Exception as e:
4142
logger.error(f"Decryption error: {e!s}")
42-
raise e
43+
raise
4344

4445

4546
def get_openbis_from_cache(request):
@@ -96,17 +97,18 @@ def __init__(self, uploaded_files, selected_files):
9697

9798
def load_files(self):
9899
if not self.uploaded_files:
99-
raise ValueError("No files uploaded.")
100+
msg = "No files uploaded."
101+
raise ValueError(msg)
100102
# start countdown
101103
self.start_time = time.time()
102104

103105
file_sizes = 0
104106
for uploaded_file in self.uploaded_files:
105107
file_sizes += uploaded_file.size
106108
if self.size_limit and file_sizes > int(float(self.size_limit)):
107-
raise ValueError(
108-
f"Uploaded files exceed the size limit of {int(float(self.size_limit))} bytes.",
109-
)
109+
limit = int(float(self.size_limit))
110+
msg = f"Uploaded files exceed limit of {limit} bytes."
111+
raise ValueError(msg)
110112

111113
for uploaded_file in self.uploaded_files:
112114
if uploaded_file.name.endswith(".zip"):
@@ -117,74 +119,79 @@ def load_files(self):
117119
self._process_regular_file(uploaded_file)
118120

119121
if not self.saved_file_names:
120-
raise ValueError("No files were saved. Processing may have failed.")
122+
msg = "No files were saved. Processing may have failed."
123+
raise ValueError(msg)
121124
return self.saved_file_names
122125

123126
def _process_zip(self, uploaded_file):
124-
tmp_dir = tempfile.mkdtemp()
127+
tmp_dir = Path(tempfile.mkdtemp())
125128
self.temp_dirs.append(tmp_dir)
126-
zip_path = os.path.join(tmp_dir, uploaded_file.name)
127-
with open(zip_path, "wb") as f:
129+
zip_path = tmp_dir / uploaded_file.name
130+
with Path.open(zip_path, "wb") as f:
128131
for chunk in uploaded_file.chunks():
129132
f.write(chunk)
130133

131134
with zipfile.ZipFile(zip_path, "r") as zip_ref:
132135
for zip_info in zip_ref.infolist():
133136
if not zip_info.is_dir():
134-
target_path = os.path.join(tmp_dir, zip_info.filename)
135-
os.makedirs(os.path.dirname(target_path), exist_ok=True)
137+
target_path = tmp_dir / zip_info.filename
138+
target_path.parent.mkdir(parents=True, exist_ok=True)
136139
# read zip member in chunks to allow timeout checks
137140
with (
138141
zip_ref.open(zip_info) as src,
139-
open(target_path, "wb") as out_file,
142+
Path.open(target_path, "wb") as out_file,
140143
):
141144
while True:
142145
chunk = src.read(8192)
143146
if not chunk:
144147
break
145148
out_file.write(chunk)
146149
if zip_info.filename in self.selected_files:
147-
self.saved_file_names.append((zip_info.filename, target_path))
150+
self.saved_file_names.append(
151+
(zip_info.filename, str(target_path)),
152+
)
148153

149154
def _process_tar(self, uploaded_file):
150-
suffix = os.path.splitext(uploaded_file.name)[1]
155+
suffix = Path(uploaded_file.name).suffix
151156
tmp_tar_path = None
152157
try:
153158
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp_tar:
154159
for chunk in uploaded_file.chunks():
155160
tmp_tar.write(chunk)
156161
tmp_tar_path = tmp_tar.name
157162

158-
tmp_dir = tempfile.mkdtemp()
163+
tmp_dir = Path(tempfile.mkdtemp())
159164
self.temp_dirs.append(tmp_dir)
160165
with tarfile.open(tmp_tar_path, "r:*") as tar_ref:
161166
for member in tar_ref.getmembers():
162167
if member.isfile():
163168
if extracted_file := tar_ref.extractfile(member):
164-
target_path = os.path.join(tmp_dir, member.name)
165-
os.makedirs(os.path.dirname(target_path), exist_ok=True)
166-
with open(target_path, "wb") as out_file:
169+
target_path = tmp_dir / member.name
170+
target_path.parent.mkdir(parents=True, exist_ok=True)
171+
with Path.open(target_path, "wb") as out_file:
167172
while True:
168173
chunk = extracted_file.read(8192)
169174
if not chunk:
170175
break
171176
out_file.write(chunk)
172177
if member.name in self.selected_files:
173-
self.saved_file_names.append((member.name, target_path))
178+
self.saved_file_names.append(
179+
(member.name, str(target_path)),
180+
)
174181

175182
finally:
176-
if tmp_tar_path and os.path.exists(tmp_tar_path):
177-
os.remove(tmp_tar_path)
183+
if tmp_tar_path and Path(tmp_tar_path).exists():
184+
Path.unlink(Path(tmp_tar_path))
178185

179186
def _process_regular_file(self, uploaded_file):
180-
tmp_dir = tempfile.mkdtemp()
187+
tmp_dir = Path(tempfile.mkdtemp())
181188
self.temp_dirs.append(tmp_dir)
182-
target_path = os.path.join(tmp_dir, uploaded_file.name)
183-
with open(target_path, "wb") as f:
189+
target_path = tmp_dir / uploaded_file.name
190+
with Path.open(target_path, "wb") as f:
184191
for chunk in uploaded_file.chunks():
185192
f.write(chunk)
186193
if uploaded_file.name in self.selected_files:
187-
self.saved_file_names.append((uploaded_file.name, target_path))
194+
self.saved_file_names.append((uploaded_file.name, str(target_path)))
188195

189196
def antivirus_scan(self):
190197
# Placeholder for antivirus scanning logic
@@ -204,7 +211,8 @@ def assign_parsers(self, request):
204211
for idx, (file_name, file_path) in enumerate(self.uploaded_files):
205212
parser_name = request.POST.get(f"parser_type_{idx}")
206213
if not parser_name:
207-
raise ValueError(f"No parser selected for file {file_name}")
214+
msg = f"No parser selected for file {file_name}"
215+
raise ValueError(msg)
208216

209217
if parser_name not in self.parser_instances:
210218
for parser in self.available_parsers.values():
@@ -225,20 +233,24 @@ def __init__(self, uploaded_files):
225233

226234
def cleanup(self):
227235
for _, temp_file in self.uploaded_files:
228-
temp_dir = os.path.dirname(temp_file)
229-
if os.path.exists(temp_dir):
236+
temp_dir = Path(temp_file).parent
237+
if temp_dir.exists():
230238
shutil.rmtree(temp_dir, ignore_errors=True)
231239
self.uploaded_files.clear()
232240

233241

234-
def log_results(request, parsed_files={}, context={}):
242+
def log_results(request, parsed_files=None, context=None):
243+
if parsed_files is None:
244+
parsed_files = {}
245+
if context is None:
246+
context = {}
235247
log_storage.clear()
236248
for parser, paths in parsed_files.items():
237249
for path in paths:
238250
log_storage.append(
239251
{
240-
"event": f"[{parser}] Parsed: {os.path.basename(path)}",
241-
"timestamp": datetime.datetime.now().isoformat(),
252+
"event": f"[{parser}] Parsed: {Path(path).name}",
253+
"timestamp": datetime.datetime.now(tz=datetime.UTC).isoformat(),
242254
"level": "info",
243255
},
244256
)
@@ -299,8 +311,7 @@ def reorganize_spaces(spaces: list[str]) -> list[str]:
299311

300312
# Sort by numeric value, not lexicographically (VP.2 < VP.10)
301313
def vp_sort_key(vp_key: str) -> int:
302-
n = int(vp_key.split(".")[1])
303-
return n
314+
return int(vp_key.split(".")[1])
304315

305316
vp_spaces: list[str] = []
306317
for vp_key in sorted(vp_groups.keys(), key=vp_sort_key):

openbis_upload_helper/app/views.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import uuid
2+
from typing import Any
23

34
from bam_masterdata.cli.cli import run_parser
45
from bam_masterdata.logger import logger
@@ -59,7 +60,7 @@ def login(request):
5960
cache.set(session_id, o, timeout=60 * 60) # Cache for 1 hour (adjustable)
6061
return redirect("homepage")
6162

62-
except Exception as e:
63+
except (ValueError, RuntimeError, ConnectionError) as e:
6364
logger.error(f"Login failed for user '{username}': {e}", exc_info=True)
6465
error = "Invalid username/password or personal access token."
6566

@@ -72,13 +73,13 @@ def logout_view(request):
7273
return redirect("login")
7374

7475

75-
def homepage(request):
76+
def homepage(request): # noqa: C901, PLR0911, PLR0912, PLR0915 (too complex, too many branches, too many statements)
7677
# Check if the user is logged in
7778
o = get_openbis_from_cache(request)
7879
if not o:
7980
logger.info("User not logged in, redirecting to login page.")
8081
return redirect("login")
81-
context = {}
82+
context: dict[str, Any] = {}
8283
available_parsers, parser_choices = preload_context_request(request, context)
8384

8485
# load
@@ -114,18 +115,8 @@ def homepage(request):
114115
collections_raw = o.get_experiments()
115116

116117
# Filter
117-
try:
118-
projects = [extract_name(p) for p in projects_raw]
119-
except Exception:
120-
projects = [extract_name(p) for p in projects_raw]
121-
122-
try:
123-
collections = [extract_name(c) for c in collections_raw]
124-
except Exception:
125-
collections = [extract_name(c) for c in collections_raw]
126-
127-
# context["projects"] = projects
128-
# context["collections"] = collections
118+
projects = [extract_name(p) for p in projects_raw]
119+
collections = [extract_name(c) for c in collections_raw]
129120

130121
else:
131122
projects = []
@@ -166,7 +157,7 @@ def homepage(request):
166157
request.session.pop("checker_logs", None)
167158
return redirect("homepage")
168159

169-
except Exception as e:
160+
except (OSError, ValueError) as e:
170161
logger.exception("Error while uploading files")
171162
context["error"] = str(e)
172163
return render(request, "homepage.html", context)
@@ -204,7 +195,7 @@ def homepage(request):
204195
request.session["parsers_assigned"] = True
205196
return redirect("homepage")
206197

207-
except Exception as e:
198+
except (ValueError, RuntimeError) as e:
208199
logger.exception("Error while assigning parsers")
209200
context["error"] = str(e)
210201
return render(request, "homepage.html", context)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from .load import get_entry_point_parsers
1+
from .load import get_entry_point_parsers as get_entry_point_parsers

0 commit comments

Comments
 (0)