Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
56 changes: 54 additions & 2 deletions pysyncrosim/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def _delete_project(library, name=None, pid=None, session=None,

# Delete Project using console
if pid is None:
pid = p["ID"].values[0]
pid = p["ProjectId"].values[0]
args = ["--delete", "--project", "--lib=\"%s\"" % library.location,
"--pid=%d" % pid, "--force"]
session._Session__call_console(args)
Expand Down Expand Up @@ -268,7 +268,7 @@ def _delete_scenario(library, project, name=None, sid=None, session=None,

# Delete Scenario using console
if sid is None:
sid = s["Scenario ID"].values[0]
sid = s["ScenarioId"].values[0]
args = ["--delete", "--scenario", "--lib=\"%s\"" % library.location,
"--sid=%d" % sid, "--force"]
session._Session__call_console(args)
Expand All @@ -277,3 +277,55 @@ def _delete_scenario(library, project, name=None, sid=None, session=None,
library._Library__scenarios = None
library._Library__init_scenarios()

def _delete_folder(library, fid, session=None, force=False):

if session is None:
session = ps.Session()

if force is False:
answer = input(f"Are you sure you want to delete folder {fid} (Y/N)?")
else:
answer = "Y"

if answer == "Y":

# Retrieve Folder DataFrame
args = [f"--lib={library.location}", "--list", "--folders"]
folder_data = session._Session__call_console(args, decode=True, csv=True)
folder_df = pd.read_csv(io.StringIO(folder_data))

if fid not in folder_df["Id"].values:
raise ValueError(f"Folder ID {fid} does not exist")

# Delete Folder using Console
args = ["--delete", "--folder", f"--lib={library.location}", f"--fid={fid}", "--force"]

session._Session__call_console(args)

def _delete_data(library, datasheet, pid=None, sid=None, ids=None,
session=None, force=False):

if session is None:
session = ps.Session()

if force is False:
if ids is not None:
answer = input(f"Are you sure you want to delete rows {ids} from {datasheet} (Y/N)?")
else:
answer = input(f"Are you sure you want to delete all data from {datasheet} (Y/N)?")
else:
answer = "Y"

if answer == "Y":

# Delete Data using Console
args = ["--delete", "--data", f"--lib={library.location}", f"--sheet={datasheet}", "--force"]

if pid is not None:
args += [f"--pid={pid}"]
if sid is not None:
args += [f"--sid={sid}"]
if ids is not None:
args += [f'--ids="{ids}"']

session._Session__call_console(args)
113 changes: 78 additions & 35 deletions pysyncrosim/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,8 @@ def datasheets(self, name=None, summary=True, optional=False, empty=False,

return ds

def delete(self, project=None, scenario=None, force=False, remove_backup=False, remove_publish=False, remove_custom_folders=False):
def delete(self, project=None, scenario=None, folder=None,
datasheet=None, ids=None, force=False, remove_backup=False, remove_publish=False, remove_custom_folders=False):
"""
Deletes a SyncroSim class instance.

Expand All @@ -623,17 +624,29 @@ def delete(self, project=None, scenario=None, force=False, remove_backup=False,
If called from a Library class instance, specify the Project to
delete. The default is None.
scenario : Scenario, String, or Int, optional
If called from a Scenario class instance, specify the Scenario to
If called from a Project class instance, specify the Scenario to
delete. The default is None.
folder : Folder, or Int, optional
If called from a Library class instance, specify the folder to delete. The default is None.
datasheet : String, optional
Name of the datasheet to delete data from. The default is None.
ids : String, optional
The primary key IDs for the rows to delete from the datasheet. Only used when a datasheet name is provided. The default is None.
force : Logical, optional
If set to True, does not ask user before deleting SyncroSim class
instance. The default is False.
remove_backup : Logical, optional
If True, will remove the backup folder when deleting a Library. Default is False.
If True, will remove the backup folder when deleting a Library.
Default is False.
remove_publish : Logical, optional
If True, will remove the publish folder when deleting a Library. Default is False.
If True, will remove the publish folder when deleting a Library.
Default is False.
remove_custom_folders : Logical, optional
If True and custom folders have been configured for a Library, then will remove the custom publish and/or backup folders when deleting a Library. Note that the remove_publish and remove_backup arguments must also be set to True to remove the respective custom folders. Default is False.
If True and custom folders have been configured for a Library, then
will remove the custom publish and/or backup folders when deleting
a Library. Note that the remove_publish and remove_backup arguments
must also be set to True to remove the respective custom folders.
Default is False.

Returns
-------
Expand All @@ -645,16 +658,11 @@ def delete(self, project=None, scenario=None, force=False, remove_backup=False,
# Also, should have method to delete list of Projects or Scenarios?

# type checks
if project is not None and not isinstance(project, ps.Project):
if not isinstance(project, int) and not isinstance(
project, str) and not isinstance(project, np.int64):
raise TypeError(
"project must be a Project instance, Integer, or String")
if scenario is not None and not isinstance(scenario, ps.Scenario):
if not isinstance(scenario, int) and not isinstance(
scenario, str) and not isinstance(scenario, np.int64):
raise TypeError(
"scenario must be a Scenario instance, Integer, or String")
if folder is not None and not isinstance(folder, ps.Folder):
if not isinstance(folder, int) and not isinstance(folder, np.int64):
raise TypeError("folder must be a Folder instance or Integer")
if datasheet is not None and not isinstance(datasheet, str):
raise TypeError("datasheet must be a String")

if not isinstance(force, bool):
raise TypeError("force must be a Logical")
Expand All @@ -665,45 +673,79 @@ def delete(self, project=None, scenario=None, force=False, remove_backup=False,
if not isinstance(remove_custom_folders, bool):
raise TypeError("remove_custom_folders must be a Logical")

if project is None and scenario is None:

# delete datasheet
if datasheet is not None:
helper._delete_data(library=self, datasheet=datasheet, ids=ids,
session=self.session, force=force)

# delete library
if project is None and scenario is None and folder is None and\
datasheet is None:
helper._delete_library(name = self.location, session=self.session,
force=force, remove_backup=remove_backup, remove_publish=remove_publish, remove_custom_folders=remove_custom_folders)

force=force, remove_backup=remove_backup,
remove_publish=remove_publish,
remove_custom_folders=remove_custom_folders)

# delete project scope
elif project is not None and scenario is None:

# turn project into project class instance if str or int
if type(project) is int:
p = self.projects(pid = project)
if type(project) is str:
if type(project) is int or isinstance(project, np.int64):
if project in self.__projects["ProjectId"].values:
p = self.projects(pid = project)
else:
raise ValueError(f"project {project} does not exist")
elif type(project) is str:
if project in self.__projects["Name"].values:
p = self.projects(name = project)
else:
raise ValueError(f'project {project} does not exist')
if isinstance(project, ps.Project):
raise ValueError(f"project {project} does not exist")
elif isinstance(project, ps.Project):
p = project
else:
raise TypeError(f"project must be a Project instance, "
f"Integer, or String")

helper._delete_project(library=self, name=p.name,
pid=p.pid, session=self.session,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still want to include the pid argument here because there could be cases where you have 2 projects with the same name

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

force=force)
session=self.session, force=force)

# delete scenario
elif scenario is not None:

# turn scenario into scenario class instance if str or int
if type(scenario) is int:
s = self.scenarios(sid = scenario, project = project)
if type(scenario) is str:
if type(scenario) is int or isinstance(scenario, np.int64):
if scenario in self.__scenarios["ScenarioId"].values:
s = self.scenarios(sid = scenario, project = project)
else:
raise ValueError(f"scenario {scenario} does not exist")
elif type(scenario) is str:
if scenario in self.__scenarios["Name"].values:
s = self.scenarios(name = scenario, project = project)
else:
raise ValueError(f'scenario {scenario} does not exist')
if isinstance(scenario, ps.Scenario):
raise ValueError(f"scenario {scenario} does not exist")
elif isinstance(scenario, ps.Scenario):
s = scenario
else:
raise TypeError(f"scenario must be a Scenario instance, "
f"Integer, or String")

helper._delete_scenario(library=self, project=s.project,
name=s.name, sid=s.sid,
session=self.session,
helper._delete_scenario(library=self, project=s.project,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, I think we still want the sid argument in here because you could have situations where there are scenarios with the same name but different IDs

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and added

name=s.name, session=self.session,
force=force)

# delete folder
elif folder is not None:

# turn folder into folder ID if int
if type(folder) is int or isinstance(folder, np.int64):
fid = folder
elif isinstance(folder, ps.Folder):
fid = folder.folder_id
else:
raise ValueError(f"folder {folder} does not exist")

helper._delete_folder(library=self, fid=fid, session=self.session,
force=force)

def save_datasheet(self, name, data, append=False, force=False,
scope="Library", *ids):
Expand Down Expand Up @@ -897,6 +939,7 @@ def compact(self):
try:
args = ["--compact", f"--lib={self.location}"]
self.session._Session__call_console(args)
return self.location

except RuntimeError as e:
raise RuntimeError(f"Failed to compact library with the following "
Expand Down
22 changes: 18 additions & 4 deletions pysyncrosim/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,25 +297,39 @@ def datasheets(self, name=None, summary=True, optional=False, empty=False,
return_hidden, self.pid)
return self.__datasheets

def delete(self, scenario=None, force=False):
def delete(self, scenario=None, datasheet=None, ids=None,
force=False):
"""
Deletes a Project or Scenario.
Deletes a Project, Scenario, or data from a Project scope.

Parameters
----------
scenario : Scenario, String, or Int, optional
Scenario to delete. The default is None.
datasheet : String, optional
Name of the datasheet to delete data from. The default is None.
ids : Int or String, optional
IDs of the rows to delete. If None, deletes all data. The default is
None.
force : Logical, optional
If True, does not prompt the user to confirm deletion. The default
is False.

Returns
-------
None.

"""
if datasheet is not None:
self.library.delete(datasheet=datasheet, pid=self.pid,
ids=ids, force=force)

self.library.delete(project=self, scenario=scenario, force=force)
elif scenario is not None:
self.library.delete(scenario = scenario, force = force)

else:
self.library.delete(project=self, force=force)


def save_datasheet(self, name, data, append=True, force=False):
"""
Expand Down
19 changes: 15 additions & 4 deletions pysyncrosim/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,12 +513,17 @@ def save_datasheet(self, name, data, append=False):
"""
self.library.save_datasheet(name, data, append, False, "Scenario", self.sid)

def delete(self, force=False):
def delete(self, datasheet=None, ids=None, force=False):
"""
Deletes a Scenario.
Deletes a Scenario or data from a Scenario scope.

Parameters
----------
datasheet : String, optional
Name of the datasheet to delete data from. The default is None
ids : Int or String, optional
IDs of the rows to delete. If None, deletes all data. The default is
None.
force : Logical, optional
If True, does not ask the user for permission to delete the
Scenario. The default is False.
Expand All @@ -528,8 +533,14 @@ def delete(self, force=False):
None.

"""

self.library.delete(project=self.project, scenario=self, force=force)

if datasheet is not None:
self.library.delete(datasheet=datasheet, sid=self.sid,
ids=ids, force=force)

else:
self.library.delete(project=self.project, scenario=self,
force=force)

def copy(self, name=None):
"""
Expand Down
Loading