Skip to content
This repository was archived by the owner on Jun 15, 2024. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
326980a
Functional improvements
CVilla17 Sep 23, 2022
f75d461
removing public option
CVilla17 Sep 27, 2022
1a6c6c5
Upgrade cript version to 0.5.0
rjmello Sep 29, 2022
fb88a50
Modify how File and Data objects are associated
rjmello Sep 29, 2022
5b09a65
Upload File objects first
rjmello Sep 29, 2022
c79356a
Merge pull request #34 from C-Accel-CRIPT/sdk-update
nh916 Sep 29, 2022
3151614
Attempting to solve merge conflicts
CVilla17 Sep 30, 2022
4d53301
Merge pull request #33 from C-Accel-CRIPT/Carlos-dev
rjmello Oct 7, 2022
7dec68b
Merge branch 'master' into fix_develop_branch_and_master
nh916 Nov 15, 2022
8c569f8
bumping version to 0.6.3
nh916 Nov 15, 2022
8e252aa
removed requirements_dev.txt
nh916 Nov 15, 2022
748f4cd
updated packages on requirements.txt
nh916 Nov 15, 2022
0714e0c
removing docs from master, so docs can only live in the docs branch
nh916 Nov 15, 2022
82dc9ff
removed requirements_docs.txt from master branch because everything f…
nh916 Nov 15, 2022
469e543
added pandas to dependencies and showing that we are using python 3.9+
nh916 Nov 15, 2022
cd08e2c
Merge pull request #45 from C-Accel-CRIPT/fix_develop_branch_and_master
brili Nov 16, 2022
fa3b1a2
Merge pull request #49 from C-Accel-CRIPT/readme_badges
nh916 Dec 1, 2022
be77009
Merge pull request #48 from C-Accel-CRIPT/bump_version
nh916 Dec 1, 2022
e4f797c
Merge pull request #47 from C-Accel-CRIPT/update_requirements
nh916 Dec 1, 2022
7fb5e73
Fix mac issues
Dec 15, 2022
1a7a68b
Merge pull request #53 from DBoraD/fix-mac_build
brili Dec 19, 2022
3a084f9
updated workflow (#54)
nh916 Dec 23, 2022
6991cfe
updated importing tkinter (#55)
nh916 Dec 24, 2022
c939411
Feature property method (#57)
CVilla17 Jan 3, 2023
15c43f2
Add material characteristics (#52)
CVilla17 Jan 3, 2023
4a41348
Version bump 1.0.0 (#59)
nh916 Jan 4, 2023
84bc585
fixed artifact name (#61)
nh916 Jan 4, 2023
96c6d30
update requirements.txt and bump Excel Uploader version (#67)
nh916 Jan 17, 2023
5922cc0
Resolve merge conflict between master and develop branch (#69)
nh916 Jan 18, 2023
8d6a74c
Changes to allow for smooth file uploads (#75)
CVilla17 Feb 3, 2023
5df4c49
version bump (#76)
nh916 Feb 6, 2023
b05bc7d
Fix merge conflict (#78)
nh916 Feb 14, 2023
e77b5f7
Merge branch 'develop' of github.com:C-Accel-CRIPT/cript-excel-upload…
CVilla17 Feb 14, 2023
d42cee5
Changed values in parse.py to use correct cell key
CVilla17 Feb 14, 2023
1dbb6fc
Fix cell key bug (#79)
CVilla17 Feb 14, 2023
2dcca1e
Fixing merge conflict (#80)
nh916 Feb 16, 2023
20bfb9e
Merge branch 'develop' of github.com:C-Accel-CRIPT/cript-excel-upload…
CVilla17 Mar 13, 2023
12c855b
Can add existing material nodes from other projects
CVilla17 Mar 20, 2023
0231334
got rid of a print statement
CVilla17 Mar 20, 2023
3534d39
Experiment and inventory update
CVilla17 Mar 20, 2023
9e92c51
Merge pull request #82 from C-Accel-CRIPT/experiment_and_inventory
brili Mar 23, 2023
4ad2670
Merge pull request #81 from C-Accel-CRIPT/use_existing_mat_nodes
brili Mar 23, 2023
ac1589a
Made changes to updates in response to code review comments (#85)
CVilla17 Mar 29, 2023
24a1d66
updated requirements.txt
nh916 May 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cript==0.6.1
openpyxl==3.0.10
pandas==1.5.1
black==22.10.0
pre-commit==2.20.0
eel==0.15.0
pyinstaller==5.6.2
cript==0.6.3
openpyxl==3.1.2
pandas==2.0.1
black==23.3.0
pre-commit==3.3.2
eel==0.16.0
pyinstaller==5.11.0
112 changes: 90 additions & 22 deletions src/python/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,51 @@
row_input_can_start_from = 5


def create_experiments(parsed_experiments, collection):
"""Compiles a dictionary of cript Experiment objects. If a parsed experiment is able to be turned
into an Experiment object it is added to an experiments dictionary and that dictionary is returned.
def create_experiments_and_inventories(parsed_experiments, collection):
"""Compiles dictionaries of CRIPT Experiment objects and CRIPT Inventory objects. If a parsed experiment/inventory is able to be turned
into an Experiment/Inventory object it is added to an experiments dictionary and that dictionary is returned.
parsed_...-dict of dicts
group-object
collection-object
returns- dict of objects"""
experiments = {}
inventories = {}

for key, parsed_experiment in parsed_experiments.items():
experiment_dict = {"collection": collection}

inventory_dict = {"collection": collection}
inventory = False
for parsed_cell in parsed_experiment.values():
if isinstance(parsed_cell, dict):
cell_type = parsed_cell["type"]
cell_key = parsed_cell["key"]
cell_value = parsed_cell["value"]
# Only attribute types should be in Experiment
# Only attribute and that specific identifier should be in experiment
if cell_type == "attribute":
experiment_dict[cell_key] = cell_value
inventory_dict[cell_key] = cell_value
elif cell_type == "identifier":
if cell_key == "Experiment or Inventory":
if cell_value.lower() == "i":
inventory = True
if inventory:
invObj = _create_object(cript.Inventory, inventory_dict, parsed_cell)
if invObj is not None:
inventories[key] = invObj
else:
experiment = _create_object(cript.Experiment, experiment_dict, parsed_cell)
# Only adds Experiment objects
if experiment is not None:
experiments[key] = experiment

experiment = _create_object(cript.Experiment, experiment_dict, parsed_cell)
# Only adds Experiment objects
if experiment is not None:
experiments[key] = experiment

return experiments
return experiments, inventories


def create_citations(parsed_citations, group):
"""Compiles dictionaries with Data and File cript objects.
parsed_...-dict of dicts
group-obj
returns-tuple of dicts of objs
group-cript Group node
returns-tuple of dicts of reference nodes and citation nodes
"""

references = {}
Expand Down Expand Up @@ -135,6 +146,7 @@ def create_materials(parsed_materials, project, data, citations):
citations-list
return-dict of obj"""
materials = {}
inventory_dict = {}

for key, parsed_material in parsed_materials.items():
use_existing = False
Expand All @@ -143,6 +155,8 @@ def create_materials(parsed_materials, project, data, citations):
"identifiers": [],
"properties": [],
}
belongs_in_inv = False
inv_name = None

for parsed_cell in parsed_material.values():
cell_type = parsed_cell["type"]
Expand All @@ -162,18 +176,24 @@ def create_materials(parsed_materials, project, data, citations):

elif cell_type == "property":
if parsed_cell["key"] == "use_existing":
use_existing = cellToBool(parsed_cell["value"])
use_existing = is_cell_true(parsed_cell["value"])
continue
property = _create_property(parsed_cell, data, citations)
material_dict["properties"].append(property)
elif cell_type == "relation":
belongs_in_inv = True
inv_name = cell_value

# Add characteristics to an already created material node
if use_existing:

try:
# try to get the material using its name
name_ = parsed_material["name"]["value"]
material = cript.Material.get(name=name_, project=project.uid)
mat_name = parsed_material["name"]["value"]
new_project = cript.Project.get(
name=parsed_material["use_existing"]["value"]
)
material = cript.Material.get(name=mat_name, project=new_project.uid)

# If there is a get error add it to the errors sheet
except ValueError as e:
Expand All @@ -185,22 +205,39 @@ def create_materials(parsed_materials, project, data, citations):
# If the material had a successful GET request, add properties, identifiers,
# and select attributes as written in the excel
else:

material = copyMaterial(material, new_project, project)

# Add properties,identifiers, and attributes to material
for property in material_dict["properties"]:
material.add_property(property)
for identifier in material_dict["identifiers"]:
material.add_identifier(identifier)
for key_ in material_dict:
if key_ == "keywords":
material.keywords += material_dict["keywords"]
if material.keywords is not None:
material.keywords += material_dict["keywords"]
else:
material.keywords = material_dict["keywords"]
elif key_ == "notes":
material.notes += material_dict["notes"]
if material.notes is not None:
material.notes += material_dict["notes"]
else:
material.notes = material_dict["notes"]

# create new material object otherwise
else:
material = _create_object(cript.Material, material_dict, parsed_cell)
if material is not None:

materials[key] = material
if belongs_in_inv:
if inventory_dict.get(cell_value, None):
inventory_dict[inv_name].append(material)
else:
inventory_dict[inv_name] = [material]

return materials
return materials, inventory_dict


def create_mixtures(parsed_components, materials):
Expand Down Expand Up @@ -433,7 +470,7 @@ def _create_property(parsed_property, data, citations):
property_dict["conditions"].append(condition)

elif cell_type == "method":
if cellToBool(parsed_cell["value"]):
if is_cell_true(parsed_cell["value"]):
property_dict["method"] = parsed_cell["key"]

elif cell_type == "relation":
Expand Down Expand Up @@ -530,6 +567,37 @@ def _get_relation(related_objs, cell_value, parsed_cell):
return None


def cellToBool(val):
def is_cell_true(val):
"""Converts a cell value to a useable boolean"""
return True if str(val).lower() == "true" else False
return str(val).lower() != "false"


def copyMaterial(material, new_project, project):
"""
Takes a material node and adjusts values to get rid of legacy code and incompatible features
inputs:
material - cript material node
new_project - cript project node
project - cript project node

returns - cript material node
"""
if new_project.name != project.name:
# Sets new project and gets rid of url and uid to make new node object
material.project = project
material.url = None
material.uid = None
# Gets rid of citations that would cause permissions errors
if material.group.name != project.group.name:
for property in material.properties:
property.citations = []
material.group = project.group

newProperties = []
# Gets rid of any legacy properties/custom that won't upload
for property in material.properties:
if "+" not in property.key:
newProperties.append(property)
material.properties = newProperties

return material
17 changes: 14 additions & 3 deletions src/python/excel_uploader_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,16 @@ def upload_driver(self, excel_file_path, gui_object):
# Create and validate
###

experiments = create.create_experiments(
parsed_sheets["experiment"], self.collection_object
experiments, inventories = create.create_experiments_and_inventories(
parsed_sheets["experiment & inventory"], self.collection_object
)
references, citations = create.create_citations(
parsed_sheets["citation"], self.project_object.group
)
data, files = create.create_data(
parsed_sheets["data"], self.project_object, experiments, citations
)
materials = create.create_materials(
materials, inv_dict = create.create_materials(
parsed_sheets["material"], self.project_object, data, citations
)
materials = create.create_mixtures(
Expand Down Expand Up @@ -256,6 +256,10 @@ def upload_driver(self, excel_file_path, gui_object):

upload.upload(references, "Reference", self, gui_object)

# Reassigns saved file nodes into their corresponding unsaved data nodes
for key, file in files.items():
data[key].files[0] = file

upload.upload(data, "Data", self, gui_object)

upload.upload(materials, "Material", self, gui_object)
Expand All @@ -266,6 +270,13 @@ def upload_driver(self, excel_file_path, gui_object):
parsed_sheets["data"], data, processes, self.api, self, gui_object
)

# Add saved material nodes to inventories and save inventories
for name, mat_arr in inv_dict.items():
inventory = inventories[name]
for mat in mat_arr:
inventory.add_material(mat)
upload.upload(inventories, "Inventory", self, gui_object)

return self.error_list

def get_collections_url(self):
Expand Down
6 changes: 4 additions & 2 deletions src/python/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ def parse(self):
cell_info = self._get_cell_info(index, row, column)

# Check if column should be skipped
if self._skip_column(column[1], cell_info["value"], cell_info["type"]):
if self._skip_column(
cell_info["key"], cell_info["value"], cell_info["type"]
):
continue

# Convert list values (with ";" separator) to Python lists
# Manually skip fields commonly containing semicolons
if (
cell_info["value"] not in ("notes", "description")
cell_info["key"] not in ("notes", "description")
and isinstance(cell_info["value"], str)
and ";" in cell_info["value"]
):
Expand Down
2 changes: 1 addition & 1 deletion src/python/sheet_parameters.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Define sheet parameters
sheet_parameters = [
{
"name": "experiment",
"name": "experiment & inventory",
"required_columns": ("name",),
"unique_columns": ("name",),
},
Expand Down
4 changes: 4 additions & 0 deletions src/python/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ def upload(obj_dict, obj_type, excel_uploader_object, gui_object):
continue
else:
raise error
except cript.api.exceptions.APIError as error:
obj_dict[key] = cript.File.get(
name=obj.name, project=excel_uploader_object.project_object.uid
)

# TODO this needs specific errors instead of a catch all
except Exception as error:
Expand Down