|
@@ -33,108 +33,107 @@ class Database:
|
|
|
|
|
|
if initialization:
|
|
|
# create tables
|
|
|
- with self:
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('''
|
|
|
- CREATE TABLE IF NOT EXISTS models (
|
|
|
- id INTEGER PRIMARY KEY,
|
|
|
- name TEXT NOT NULL,
|
|
|
- description TEXT,
|
|
|
- root_folder TEXT NOT NULL UNIQUE,
|
|
|
- supports TEXT NOT NULL
|
|
|
- )
|
|
|
- ''')
|
|
|
- cursor.execute('''
|
|
|
- CREATE TABLE IF NOT EXISTS label_providers (
|
|
|
- id INTEGER PRIMARY KEY,
|
|
|
- name TEXT NOT NULL,
|
|
|
- description TEXT,
|
|
|
- root_folder TEXT NOT NULL,
|
|
|
- configuration_file TEXT NOT NULL,
|
|
|
- UNIQUE(root_folder, configuration_file)
|
|
|
- )
|
|
|
- ''')
|
|
|
-
|
|
|
- cursor.execute('''
|
|
|
- CREATE TABLE IF NOT EXISTS projects (
|
|
|
- id INTEGER PRIMARY KEY,
|
|
|
- name TEXT NOT NULL,
|
|
|
- description TEXT,
|
|
|
- created INTEGER NOT NULL,
|
|
|
- model INTEGER,
|
|
|
- label_provider INTEGER,
|
|
|
- root_folder TEXT NOT NULL UNIQUE,
|
|
|
- external_data BOOL NOT NULL,
|
|
|
- data_folder TEXT NOT NULL,
|
|
|
- FOREIGN KEY (model) REFERENCES models(id)
|
|
|
- ON UPDATE CASCADE ON DELETE SET NULL,
|
|
|
- FOREIGN KEY (label_provider) REFERENCES label_providers(id)
|
|
|
- ON UPDATE CASCADE ON DELETE SET NULL
|
|
|
- )
|
|
|
- ''')
|
|
|
- cursor.execute('''
|
|
|
- CREATE TABLE IF NOT EXISTS labels (
|
|
|
- id INTEGER PRIMARY KEY,
|
|
|
- project INTEGER NOT NULL,
|
|
|
- parent INTEGER,
|
|
|
- created INTEGER NOT NULL,
|
|
|
- reference TEXT,
|
|
|
- name TEXT NOT NULL,
|
|
|
- hierarchy_level TEXT,
|
|
|
- FOREIGN KEY (project) REFERENCES projects(id)
|
|
|
- ON UPDATE CASCADE ON DELETE CASCADE,
|
|
|
- FOREIGN KEY (parent) REFERENCES labels(id)
|
|
|
- ON UPDATE CASCADE ON DELETE SET NULL,
|
|
|
- UNIQUE(project, reference)
|
|
|
- )
|
|
|
- ''')
|
|
|
- cursor.execute('''
|
|
|
- CREATE TABLE IF NOT EXISTS collections (
|
|
|
- id INTEGER PRIMARY KEY,
|
|
|
- project INTEGER NOT NULL,
|
|
|
- reference TEXT NOT NULL,
|
|
|
- name TEXT NOT NULL,
|
|
|
- description TEXT,
|
|
|
- position INTEGER NOT NULL,
|
|
|
- autoselect INTEGER NOT NULL,
|
|
|
- FOREIGN KEY (project) REFERENCES projects(id)
|
|
|
- ON UPDATE CASCADE ON DELETE CASCADE,
|
|
|
- UNIQUE(project, reference)
|
|
|
- )
|
|
|
- ''')
|
|
|
- cursor.execute('''
|
|
|
- CREATE TABLE IF NOT EXISTS files (
|
|
|
- id INTEGER PRIMARY KEY,
|
|
|
- uuid TEXT NOT NULL,
|
|
|
- project INTEGER NOT NULL,
|
|
|
- collection INTEGER,
|
|
|
- type TEXT NOT NULL,
|
|
|
- name TEXT NOT NULL,
|
|
|
- extension TEXT NOT NULL,
|
|
|
- size INTEGER NOT NULL,
|
|
|
- created INTEGER NOT NULL,
|
|
|
- path TEXT NOT NULL,
|
|
|
- frames INTEGER,
|
|
|
- fps FLOAT,
|
|
|
- FOREIGN KEY (project) REFERENCES projects(id)
|
|
|
- ON UPDATE CASCADE ON DELETE CASCADE,
|
|
|
- FOREIGN KEY (collection) REFERENCES collections(id)
|
|
|
- ON UPDATE CASCADE ON DELETE SET NULL,
|
|
|
- UNIQUE(project, path)
|
|
|
- )
|
|
|
- ''')
|
|
|
- cursor.execute('''
|
|
|
- CREATE TABLE IF NOT EXISTS results (
|
|
|
- id INTEGER PRIMARY KEY,
|
|
|
- file INTEGER NOT NULL,
|
|
|
- origin TEXT NOT NULL,
|
|
|
- type TEXT NOT NULL,
|
|
|
- label INTEGER,
|
|
|
- data TEXT,
|
|
|
- FOREIGN KEY (file) REFERENCES files(id)
|
|
|
- ON UPDATE CASCADE ON DELETE CASCADE
|
|
|
- )
|
|
|
- ''')
|
|
|
+ with self, closing(self.con.cursor()) as cursor:
|
|
|
+ cursor.execute('''
|
|
|
+ CREATE TABLE IF NOT EXISTS models (
|
|
|
+ id INTEGER PRIMARY KEY,
|
|
|
+ name TEXT NOT NULL,
|
|
|
+ description TEXT,
|
|
|
+ root_folder TEXT NOT NULL UNIQUE,
|
|
|
+ supports TEXT NOT NULL
|
|
|
+ )
|
|
|
+ ''')
|
|
|
+ cursor.execute('''
|
|
|
+ CREATE TABLE IF NOT EXISTS label_providers (
|
|
|
+ id INTEGER PRIMARY KEY,
|
|
|
+ name TEXT NOT NULL,
|
|
|
+ description TEXT,
|
|
|
+ root_folder TEXT NOT NULL,
|
|
|
+ configuration_file TEXT NOT NULL,
|
|
|
+ UNIQUE(root_folder, configuration_file)
|
|
|
+ )
|
|
|
+ ''')
|
|
|
+
|
|
|
+ cursor.execute('''
|
|
|
+ CREATE TABLE IF NOT EXISTS projects (
|
|
|
+ id INTEGER PRIMARY KEY,
|
|
|
+ name TEXT NOT NULL,
|
|
|
+ description TEXT,
|
|
|
+ created INTEGER NOT NULL,
|
|
|
+ model INTEGER,
|
|
|
+ label_provider INTEGER,
|
|
|
+ root_folder TEXT NOT NULL UNIQUE,
|
|
|
+ external_data BOOL NOT NULL,
|
|
|
+ data_folder TEXT NOT NULL,
|
|
|
+ FOREIGN KEY (model) REFERENCES models(id)
|
|
|
+ ON UPDATE CASCADE ON DELETE SET NULL,
|
|
|
+ FOREIGN KEY (label_provider) REFERENCES label_providers(id)
|
|
|
+ ON UPDATE CASCADE ON DELETE SET NULL
|
|
|
+ )
|
|
|
+ ''')
|
|
|
+ cursor.execute('''
|
|
|
+ CREATE TABLE IF NOT EXISTS labels (
|
|
|
+ id INTEGER PRIMARY KEY,
|
|
|
+ project INTEGER NOT NULL,
|
|
|
+ parent INTEGER,
|
|
|
+ created INTEGER NOT NULL,
|
|
|
+ reference TEXT,
|
|
|
+ name TEXT NOT NULL,
|
|
|
+ hierarchy_level TEXT,
|
|
|
+ FOREIGN KEY (project) REFERENCES projects(id)
|
|
|
+ ON UPDATE CASCADE ON DELETE CASCADE,
|
|
|
+ FOREIGN KEY (parent) REFERENCES labels(id)
|
|
|
+ ON UPDATE CASCADE ON DELETE SET NULL,
|
|
|
+ UNIQUE(project, reference)
|
|
|
+ )
|
|
|
+ ''')
|
|
|
+ cursor.execute('''
|
|
|
+ CREATE TABLE IF NOT EXISTS collections (
|
|
|
+ id INTEGER PRIMARY KEY,
|
|
|
+ project INTEGER NOT NULL,
|
|
|
+ reference TEXT NOT NULL,
|
|
|
+ name TEXT NOT NULL,
|
|
|
+ description TEXT,
|
|
|
+ position INTEGER NOT NULL,
|
|
|
+ autoselect INTEGER NOT NULL,
|
|
|
+ FOREIGN KEY (project) REFERENCES projects(id)
|
|
|
+ ON UPDATE CASCADE ON DELETE CASCADE,
|
|
|
+ UNIQUE(project, reference)
|
|
|
+ )
|
|
|
+ ''')
|
|
|
+ cursor.execute('''
|
|
|
+ CREATE TABLE IF NOT EXISTS files (
|
|
|
+ id INTEGER PRIMARY KEY,
|
|
|
+ uuid TEXT NOT NULL,
|
|
|
+ project INTEGER NOT NULL,
|
|
|
+ collection INTEGER,
|
|
|
+ type TEXT NOT NULL,
|
|
|
+ name TEXT NOT NULL,
|
|
|
+ extension TEXT NOT NULL,
|
|
|
+ size INTEGER NOT NULL,
|
|
|
+ created INTEGER NOT NULL,
|
|
|
+ path TEXT NOT NULL,
|
|
|
+ frames INTEGER,
|
|
|
+ fps FLOAT,
|
|
|
+ FOREIGN KEY (project) REFERENCES projects(id)
|
|
|
+ ON UPDATE CASCADE ON DELETE CASCADE,
|
|
|
+ FOREIGN KEY (collection) REFERENCES collections(id)
|
|
|
+ ON UPDATE CASCADE ON DELETE SET NULL,
|
|
|
+ UNIQUE(project, path)
|
|
|
+ )
|
|
|
+ ''')
|
|
|
+ cursor.execute('''
|
|
|
+ CREATE TABLE IF NOT EXISTS results (
|
|
|
+ id INTEGER PRIMARY KEY,
|
|
|
+ file INTEGER NOT NULL,
|
|
|
+ origin TEXT NOT NULL,
|
|
|
+ type TEXT NOT NULL,
|
|
|
+ label INTEGER,
|
|
|
+ data TEXT,
|
|
|
+ FOREIGN KEY (file) REFERENCES files(id)
|
|
|
+ ON UPDATE CASCADE ON DELETE CASCADE
|
|
|
+ )
|
|
|
+ ''')
|
|
|
|
|
|
if discovery:
|
|
|
# run discovery modules
|
|
@@ -171,16 +170,47 @@ class Database:
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
|
self.con.__exit__(exc_type, exc_val, exc_tb)
|
|
|
|
|
|
+ def get_object_by_id(self, table_name: str, identifier: int, cls):
|
|
|
+ """
|
|
|
+ create an object from cls and a row fetched from table_name and
|
|
|
+ identified by the identifier
|
|
|
+
|
|
|
+ :param table_name: table name
|
|
|
+ :param identifier: unique identifier
|
|
|
+ :param cls: class that is used to create the object
|
|
|
+ :return: object of type cls
|
|
|
+ """
|
|
|
+ with closing(self.con.cursor()) as cursor:
|
|
|
+ cursor.execute(f'SELECT * FROM {table_name} WHERE id = ?', [identifier])
|
|
|
+ row = cursor.fetchone()
|
|
|
+
|
|
|
+ if row is not None:
|
|
|
+ return cls(self, row)
|
|
|
+
|
|
|
+ return None
|
|
|
+
|
|
|
+ def get_objects(self, table_name: str, cls):
|
|
|
+ """
|
|
|
+ get a list of all available objects in the table
|
|
|
+
|
|
|
+ :param table_name: table name
|
|
|
+ :param cls: class that is used to create the objects
|
|
|
+ :return: list of object of type cls
|
|
|
+ """
|
|
|
+
|
|
|
+ with closing(self.con.cursor()) as cursor:
|
|
|
+ cursor.execute(f'SELECT * FROM {table_name}')
|
|
|
+ for row in cursor:
|
|
|
+ yield cls(self, row)
|
|
|
+
|
|
|
+
|
|
|
def models(self) -> Iterator[Model]:
|
|
|
"""
|
|
|
get a list of all available models
|
|
|
|
|
|
:return: iterator of models
|
|
|
"""
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('SELECT * FROM models')
|
|
|
- for row in cursor:
|
|
|
- yield Model(self, row)
|
|
|
+ return self.get_objects("models", Model)
|
|
|
|
|
|
def model(self, identifier: int) -> Optional[Model]:
|
|
|
"""
|
|
@@ -189,14 +219,7 @@ class Database:
|
|
|
:param identifier: unique identifier
|
|
|
:return: model
|
|
|
"""
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('SELECT * FROM models WHERE id = ?', [identifier])
|
|
|
- row = cursor.fetchone()
|
|
|
-
|
|
|
- if row is not None:
|
|
|
- return Model(self, row)
|
|
|
-
|
|
|
- return None
|
|
|
+ return self.get_object_by_id("models", identifier, Model)
|
|
|
|
|
|
def label_providers(self) -> Iterator[LabelProvider]:
|
|
|
"""
|
|
@@ -204,10 +227,7 @@ class Database:
|
|
|
|
|
|
:return: iterator over label providers
|
|
|
"""
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('SELECT * FROM label_providers')
|
|
|
- for row in cursor:
|
|
|
- yield LabelProvider(self, row)
|
|
|
+ return self.get_objects("label_providers", LabelProvider)
|
|
|
|
|
|
def label_provider(self, identifier: int) -> Optional[LabelProvider]:
|
|
|
"""
|
|
@@ -216,14 +236,7 @@ class Database:
|
|
|
:param identifier: unique identifier
|
|
|
:return: label provider
|
|
|
"""
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('SELECT * FROM label_providers WHERE id = ?', [identifier])
|
|
|
- row = cursor.fetchone()
|
|
|
-
|
|
|
- if row is not None:
|
|
|
- return LabelProvider(self, row)
|
|
|
-
|
|
|
- return None
|
|
|
+ return self.get_object_by_id("label_providers", identifier, LabelProvider)
|
|
|
|
|
|
def projects(self) -> Iterator[Project]:
|
|
|
"""
|
|
@@ -231,10 +244,7 @@ class Database:
|
|
|
|
|
|
:return: iterator over projects
|
|
|
"""
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('SELECT * FROM projects')
|
|
|
- for row in cursor:
|
|
|
- yield Project(self, row)
|
|
|
+ return self.get_objects("projects", Project)
|
|
|
|
|
|
def project(self, identifier: int) -> Optional[Project]:
|
|
|
"""
|
|
@@ -243,14 +253,7 @@ class Database:
|
|
|
:param identifier: unique identifier
|
|
|
:return: project
|
|
|
"""
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('SELECT * FROM projects WHERE id = ?', [identifier])
|
|
|
- row = cursor.fetchone()
|
|
|
-
|
|
|
- if row is not None:
|
|
|
- return Project(self, row)
|
|
|
-
|
|
|
- return None
|
|
|
+ return self.get_object_by_id("projects", identifier, Project)
|
|
|
|
|
|
def create_project(self,
|
|
|
name: str,
|
|
@@ -296,14 +299,7 @@ class Database:
|
|
|
:param identifier: unique identifier
|
|
|
:return: collection
|
|
|
"""
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('SELECT * FROM collections WHERE id = ?', [identifier])
|
|
|
- row = cursor.fetchone()
|
|
|
-
|
|
|
- if row is not None:
|
|
|
- return Collection(self, row)
|
|
|
-
|
|
|
- return None
|
|
|
+ return self.get_object_by_id("collections", identifier, Collection)
|
|
|
|
|
|
def file(self, identifier) -> Optional[File]:
|
|
|
"""
|
|
@@ -312,14 +308,7 @@ class Database:
|
|
|
:param identifier: unique identifier
|
|
|
:return: file
|
|
|
"""
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('SELECT * FROM files WHERE id = ?', [identifier])
|
|
|
- row = cursor.fetchone()
|
|
|
-
|
|
|
- if row is not None:
|
|
|
- return File(self, row)
|
|
|
-
|
|
|
- return None
|
|
|
+ return self.get_object_by_id("files", identifier, File)
|
|
|
|
|
|
def result(self, identifier) -> Optional[Result]:
|
|
|
"""
|
|
@@ -328,11 +317,4 @@ class Database:
|
|
|
:param identifier: unique identifier
|
|
|
:return: result
|
|
|
"""
|
|
|
- with closing(self.con.cursor()) as cursor:
|
|
|
- cursor.execute('SELECT * FROM results WHERE id = ?', [identifier])
|
|
|
- row = cursor.fetchone()
|
|
|
-
|
|
|
- if row is not None:
|
|
|
- return Result(self, row)
|
|
|
-
|
|
|
- return None
|
|
|
+ return self.get_object_by_id("results", identifier, Result)
|