MAJOR: solves problem related to ELABFTW_API_URL variable

if no value was specified for such variable (or .env was missing)
EAU would be set to None and get stuck in a prompt loop

solved by turning EAU into a required variable in APIHandler
(and editing a lot of code through all of src/)
This commit is contained in:
2026-05-14 17:24:02 +02:00
parent 1ce381f341
commit 685d15d55b
3 changed files with 56 additions and 36 deletions

View File

@@ -23,11 +23,11 @@ class APIHandler:
# TO-DO: remove static url.
def __init__(self, api_key="", ELABFTW_API_URL=None):
"""Init method, api_key suggested but not required (empty by default)."""
if not ELABFTW_API_URL:
load_dotenv()
ELABFTW_API_URL = os.getenv("ELABFTW_API_URL") or input(
"Enter a valid eLabFTW API URL (ends with '/api/v2)': "
)
# if not ELABFTW_API_URL:
# load_dotenv()
# ELABFTW_API_URL = os.getenv("ELABFTW_API_URL") or input(
# "Enter a valid eLabFTW API URL (ends with '/api/v2)': "
# )
self.api_key = api_key
self.auth = {"Authorization": api_key}
self.content = {"Content-Type": "application/json"}

View File

@@ -134,7 +134,7 @@ class Layer:
self.start_time = layer_data.get("created_at") or None
self.description = layer_data.get("body") or None
def get_instruments(self, api_key):
def get_instruments(self, api_key, ELABFTW_API_URL):
"""
Retruns a dictionary of all the instruments used to create the layer.
The format of the dictionary is:
@@ -144,18 +144,20 @@ class Layer:
"rheed_system": str
}
Arg: api_key: str: A valid API key for the eLabFTW instance where the data is stored, with permissions to access the relevant entries.
eLabFTW's API keys are well documented here: https://doc.elabftw.net/docs/usage/api/.
If you don't have an API key and are uncapable of creating one, contact your eLabFTW administrator.
Or RTFM and create one yourself, it's not that hard.
Args:
api_key: str: A valid API key for the eLabFTW instance where the data is stored, with permissions to access the relevant entries.
eLabFTW's API keys are well documented here: https://doc.elabftw.net/docs/usage/api/.
If you don't have an API key and are uncapable of creating one, contact your eLabFTW administrator.
Or RTFM and create one yourself, it's not that hard.
ELABFTW_API_URL: str: URL for the API root endpoint of the eLabFTW instance. Ends with '/api/v2' - no trailing slash.
"""
raw_lasersys_data = APIHandler(api_key).get_entry_from_elabid(
raw_lasersys_data = APIHandler(api_key, ELABFTW_API_URL).get_entry_from_elabid(
self.laser_system_elabid, entryType="items"
)
raw_chamber_data = APIHandler(api_key).get_entry_from_elabid(
raw_chamber_data = APIHandler(api_key, ELABFTW_API_URL).get_entry_from_elabid(
self.chamber_elabid, entryType="items"
)
raw_rheedsys_data = APIHandler(api_key).get_entry_from_elabid(
raw_rheedsys_data = APIHandler(api_key, ELABFTW_API_URL).get_entry_from_elabid(
self.rheed_system_elabid, entryType="items"
)
instruments_used = {
@@ -248,6 +250,7 @@ class Entrypoint:
* linked_experiments_elabid: list: List of eLabFTW internal id's of the experiments linked to the entrypoint.
"""
try:
self.name = sample_data["title"]
self.extra = sample_data["metadata_decoded"]["extra_fields"]
self.linked_items = sample_data["items_links"] # dict
self.batch_elabid = self.extra["Substrate batch"]["value"] # elabid
@@ -262,11 +265,6 @@ class Entrypoint:
raise KeyError(
f'The provided dictionary lacks a "{k}" key. Check the sample entry on eLabFTW and make sure you used the correct Resource template.'
)
# Non-required attributes:
self.name = (
sample_data.get("title") or None
) # error prevention is more important than preventing empty fields here
# although I don't think it's even possible to fuck up this bad...
class Material:
@@ -310,7 +308,7 @@ class Material:
f'The provided dictionary lacks a "{k}" key. Check the target/substrate entry on eLabFTW and make sure you used the correct Resource template.'
)
def get_compound_data(self, apikey):
def get_compound_data(self, apikey, ELABFTW_API_URL):
"""
Returns a dictionary with the relevant data on the compound of which the material is made.
The format of the dictionary is:
@@ -320,12 +318,14 @@ class Material:
"cas_number": str
}
Arg: api_key: str: A valid API key for the eLabFTW instance where the data is stored, with permissions to access the relevant entries.
eLabFTW's API keys are well documented here: https://doc.elabftw.net/docs/usage/api/.
If you don't have an API key and are uncapable of creating one, contact your eLabFTW administrator.
Or RTFM and create one yourself, it's not that hard.
Args:
api_key: str: A valid API key for the eLabFTW instance where the data is stored, with permissions to access the relevant entries.
eLabFTW's API keys are well documented here: https://doc.elabftw.net/docs/usage/api/.
If you don't have an API key and are uncapable of creating one, contact your eLabFTW administrator.
Or RTFM and create one yourself, it's not that hard.
ELABFTW_API_URL: str: URL for the API root endpoint of the eLabFTW instance. Ends with '/api/v2' - no trailing slash.
"""
raw_compound_data = APIHandler(apikey).get_entry_from_elabid(
raw_compound_data = APIHandler(apikey, ELABFTW_API_URL).get_entry_from_elabid(
self.compound_elabid, entryType="items"
)
name = raw_compound_data["title"]
@@ -339,8 +339,20 @@ class Material:
}
return compound_data
def get_compound_formula(self, apikey):
formula = self.get_compound_data(apikey).get("chemical_formula")
def get_compound_formula(self, apikey, ELABFTW_API_URL):
"""
Returns a string with the chemical formula of the compound.
Args:
api_key: str: A valid API key for the eLabFTW instance where the data is stored, with permissions to access the relevant entries.
eLabFTW's API keys are well documented here: https://doc.elabftw.net/docs/usage/api/.
If you don't have an API key and are uncapable of creating one, contact your eLabFTW administrator.
Or RTFM and create one yourself, it's not that hard.
ELABFTW_API_URL: str: URL for the API root endpoint of the eLabFTW instance. Ends with '/api/v2' - no trailing slash.
"""
formula = self.get_compound_data(apikey, ELABFTW_API_URL).get(
"chemical_formula"
)
return formula
@@ -454,7 +466,8 @@ if __name__ == "__main__":
# print(f"Example header:\n\t{head.header}\n")
# print("Warning: you're not supposed to be running this as the main program.")
api_key = getpass("Paste API key here [no echo]: ")
handler = APIHandler(api_key=api_key)
ELABFTW_API_URL = input("Enter a valid eLabFTW API URL (ends with '/api/v2)': ")
handler = APIHandler(api_key, ELABFTW_API_URL)
exp58 = handler.get_entry_from_elabid(elabid=58, entryType="experiments")
layer58 = Layer(exp58)
print(layer58.list_attachments())

View File

@@ -20,7 +20,7 @@ def call_entrypoint_from_elabid(elabid):
Arg: elabid: int eLabFTW internal id of the selected resource.
"""
try:
sample_data = APIHandler(api_key).get_entry_from_elabid(
sample_data = APIHandler(api_key, ELABFTW_API_URL).get_entry_from_elabid(
elabid, entryType="items"
)
if not sample_data.get("category_title") == "Sample":
@@ -44,7 +44,7 @@ def call_material_from_elabid(elabid):
arg: elabid: int eLabFTW internal id of the selected resource.
"""
try:
material_data = APIHandler(api_key).get_entry_from_elabid(
material_data = APIHandler(api_key, ELABFTW_API_URL).get_entry_from_elabid(
elabid, entryType="items"
)
material_category = material_data.get("category_title")
@@ -75,7 +75,7 @@ def call_layers_from_list(elabid_list):
list_of_layers = []
for elabid in elabid_list:
try:
layer_data = APIHandler(api_key).get_entry_from_elabid(
layer_data = APIHandler(api_key, ELABFTW_API_URL).get_entry_from_elabid(
elabid, entryType="experiments"
)
if not layer_data.get("category_title") == "PLD Deposition":
@@ -106,7 +106,7 @@ def call_proposal_from_elabid(elabid):
Arg: elabid: int eLabFTW internal id of the selected resource.
"""
try:
proposal_data = APIHandler(api_key).get_entry_from_elabid(
proposal_data = APIHandler(api_key, ELABFTW_API_URL).get_entry_from_elabid(
elabid, entryType="items"
)
proposal_category = proposal_data.get("category_title")
@@ -186,7 +186,7 @@ def deduplicate_instruments_from_layers(layers):
rheeds = []
elegant_dict = {}
for lyr in layers:
instruments = lyr.get_instruments(api_key)
instruments = lyr.get_instruments(api_key, ELABFTW_API_URL)
lasers.append(instruments["laser_system"])
chambers.append(instruments["deposition_chamber"])
rheeds.append(instruments["rheed_system"])
@@ -356,7 +356,9 @@ def make_nexus_schema_dictionary(substrate_object, layers):
"sample": {
"substrate": {
"name": substrate_object.name,
"chemical_formula": substrate_object.get_compound_formula(api_key),
"chemical_formula": substrate_object.get_compound_formula(
api_key, ELABFTW_API_URL
),
"orientation": substrate_object.orientation,
"miscut_angle": {
"value": substrate_object.miscut_angle,
@@ -384,7 +386,9 @@ def make_nexus_schema_dictionary(substrate_object, layers):
target_object = chain_layer_to_target(layer)
target_dict = {
"name": target_object.name,
"chemical_formula": target_object.get_compound_formula(api_key),
"chemical_formula": target_object.get_compound_formula(
api_key, ELABFTW_API_URL
),
"description": target_object.description,
"shape": target_object.shape,
"dimensions": target_object.dimensions,
@@ -772,7 +776,7 @@ def build_nexus_file(pld_fabrication, output_path="output/nffa-di_unnamed.h5"):
n = layer_dict["layer_number"]
rheed_data_file = layer_dict["data"][0] # first in the tuple
rheed_image_file = layer_dict["data"][1] # second in the tuple
handler = APIHandler(api_key)
handler = APIHandler(api_key, ELABFTW_API_URL)
# TO-DO: maybe make a dedicated function???
data_path = None
@@ -877,7 +881,10 @@ if __name__ == "__main__":
or input("Enter elabid of your starting sample [default = 1111]: ")
or 1111
)
handler = APIHandler(api_key)
ELABFTW_API_URL = os.getenv("ELABFTW_API_URL") or input(
"Enter a valid eLabFTW API URL (ends with '/api/v2)': "
)
handler = APIHandler(api_key, ELABFTW_API_URL)
data = handler.get_entry_from_elabid(elabid)
sample = Entrypoint(data)
sample_name = sample.name.strip().replace(