Coverage for /builds/ase/ase/ase/db/project.py: 97.87%

47 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-08-02 00:12 +0000

1# fmt: off 

2 

3from pathlib import Path 

4 

5from ase.db.core import KeyDescription 

6from ase.db.row import row2dct 

7from ase.formula import Formula 

8 

9 

10class DatabaseProject: 

11 """Settings for web view of a database. 

12 

13 For historical reasons called a "Project". 

14 """ 

15 _ase_templates = Path('ase/db/templates') 

16 

17 def __init__(self, name, title, *, 

18 key_descriptions, 

19 database, 

20 default_columns): 

21 self.name = name 

22 self.title = title 

23 self.uid_key = 'id' 

24 

25 # The templates loop over "key descriptions" when they want to 

26 # loop over keys. 

27 # 

28 # Therefore, any key without description will not be rendered. 

29 # Therefore, we need to make dummy key descriptions of everything 

30 # in the database, ensuring that all keys are visible. 

31 

32 all_keys = database.get_all_key_names() 

33 

34 key_descriptions = { 

35 **{key: KeyDescription(key) for key in all_keys}, 

36 **key_descriptions} 

37 

38 for key, value in key_descriptions.items(): 

39 assert isinstance(key, str), type(key) 

40 assert isinstance(value, KeyDescription), type(value) 

41 

42 self.key_descriptions = key_descriptions 

43 self.database = database 

44 self.default_columns = default_columns 

45 

46 def get_search_template(self): 

47 return self._ase_templates / 'search.html' 

48 

49 def get_row_template(self): 

50 return self._ase_templates / 'row.html' 

51 

52 def get_table_template(self): 

53 return self._ase_templates / 'table.html' 

54 

55 def handle_query(self, args) -> str: 

56 """Convert request args to ase.db query string.""" 

57 return args['query'] 

58 

59 def row_to_dict(self, row): 

60 """Convert row to dict for use in html template.""" 

61 dct = row2dct(row, self.key_descriptions) 

62 dct['formula'] = Formula(row.formula).convert('abc').format('html') 

63 return dct 

64 

65 def uid_to_row(self, uid): 

66 return self.database.get(f'{self.uid_key}={uid}') 

67 

68 @classmethod 

69 def dummyproject(cls, **kwargs): 

70 class DummyDatabase: 

71 def select(self, *args, **kwargs): 

72 return iter([]) 

73 

74 def get_all_key_names(self): 

75 return set() 

76 

77 _kwargs = dict( 

78 name='test', 

79 title='test', 

80 key_descriptions={}, 

81 database=DummyDatabase(), # XXX 

82 default_columns=[]) 

83 _kwargs.update(kwargs) 

84 return cls(**_kwargs) 

85 

86 # If we make this a classmethod, and try to instantiate the class, 

87 # it would fail on subclasses. So we use staticmethod 

88 @staticmethod 

89 def load_db_as_ase_project(name, database): 

90 from ase.db.core import get_key_descriptions 

91 from ase.db.table import all_columns 

92 

93 return DatabaseProject( 

94 name=name, 

95 title=database.metadata.get('title', ''), 

96 key_descriptions=get_key_descriptions(), 

97 database=database, 

98 default_columns=all_columns)