@@ -72,37 +72,65 @@ class NamespaceORM(BaseORM):
7272 nullable = True ,
7373 index = True ,
7474 )
75- user : Mapped [UserORM | None ] = relationship (lazy = "joined" , init = False , repr = False , viewonly = True )
75+ user : Mapped [UserORM | None ] = relationship (
76+ lazy = "joined" , back_populates = "namespace" , init = False , repr = False , viewonly = True
77+ )
7678
77- def dump (self ) -> models .Namespace :
78- """Create a namespace model from the ORM."""
79- if self .group_id and self .group :
80- return models .Namespace (
81- id = self .id ,
82- slug = self .slug ,
83- kind = models .NamespaceKind .group ,
84- created_by = self .group .created_by ,
85- underlying_resource_id = self .group_id ,
86- latest_slug = self .slug ,
87- name = self .group .name ,
88- )
79+ @property
80+ def created_by (self ) -> str :
81+ """User that created this namespace."""
82+ if self .group is not None :
83+ return self .group .created_by
84+ elif self .user_id :
85+ return self .user_id
86+ raise errors .ProgrammingError (
87+ message = f"Found a namespace { self .slug } that has no group or user associated with it."
88+ )
8989
90- if not self .user or not self .user_id :
91- raise errors .ProgrammingError (message = "Found a namespace that has no group or user associated with it." )
90+ @property
91+ def creation_date (self ) -> datetime | None :
92+ """When this namespace was created."""
93+ return self .group .creation_date if self .group else None
94+
95+ @property
96+ def underlying_resource_id (self ) -> str | ULID :
97+ """Return the id of the underlying resource."""
98+ if self .group_id is not None :
99+ return self .group_id
100+ elif self .user_id is not None :
101+ return self .user_id
102+
103+ raise errors .ProgrammingError (
104+ message = f"Found a namespace { self .slug } that has no group or user associated with it."
105+ )
92106
93- name = (
94- f"{ self .user .first_name } { self .user .last_name } "
95- if self .user .first_name and self .user .last_name
96- else self .user .first_name or self .user .last_name
107+ @property
108+ def name (self ) -> str | None :
109+ """Return the name of the underlying resource."""
110+ if self .group is not None :
111+ return self .group .name
112+ elif self .user is not None :
113+ return (
114+ f"{ self .user .first_name } { self .user .last_name } "
115+ if self .user .first_name and self .user .last_name
116+ else self .user .first_name or self .user .last_name
117+ )
118+ raise errors .ProgrammingError (
119+ message = f"Found a namespace { self .slug } that has no group or user associated with it."
97120 )
121+
122+ def dump (self ) -> models .Namespace :
123+ """Create a namespace model from the ORM."""
124+ kind = models .NamespaceKind .group if self .group else models .NamespaceKind .user
98125 return models .Namespace (
99126 id = self .id ,
100127 slug = self .slug ,
101- kind = models .NamespaceKind .user ,
102- created_by = self .user_id ,
103- underlying_resource_id = self .user_id ,
128+ kind = kind ,
129+ created_by = self .created_by ,
130+ creation_date = self .creation_date ,
131+ underlying_resource_id = self .underlying_resource_id ,
104132 latest_slug = self .slug ,
105- name = name ,
133+ name = self . name ,
106134 )
107135
108136 def dump_user (self ) -> UserInfo :
@@ -112,6 +140,8 @@ def dump_user(self) -> UserInfo:
112140 message = "Cannot dump ORM namespace as namespace with user if the namespace "
113141 "has no associated user with it."
114142 )
143+ # NOTE: calling `self.user.dump()` can cause sqlalchemy greenlet errors, as it tries to fetch the namespace
144+ # again from the db, even though the back_populates should take care of this and not require loading.
115145 ns = self .dump ()
116146 user_info = UserInfo (
117147 id = self .user .keycloak_id ,
@@ -154,7 +184,8 @@ def dump(self) -> models.Namespace:
154184 id = self .id ,
155185 slug = self .slug ,
156186 latest_slug = self .slug ,
157- created_by = self .latest_slug .group .created_by ,
187+ created_by = self .latest_slug .created_by ,
188+ creation_date = self .created_at ,
158189 kind = models .NamespaceKind .group ,
159190 underlying_resource_id = self .latest_slug .group_id ,
160191 name = self .latest_slug .group .name ,
@@ -175,6 +206,7 @@ def dump(self) -> models.Namespace:
175206 slug = self .slug ,
176207 latest_slug = self .latest_slug .slug ,
177208 created_by = self .latest_slug .user_id ,
209+ creation_date = self .created_at ,
178210 kind = models .NamespaceKind .user ,
179211 underlying_resource_id = self .latest_slug .user_id ,
180212 name = name ,
0 commit comments