Coverage for gws-app/gws/base/exporter/worker.py: 81%

78 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-24 12:46 +0200

1from typing import Optional, cast 

2 

3import gws 

4import gws.base.job 

5 

6 

7class Object(gws.base.job.worker.Object): 

8 project: gws.Project 

9 request: gws.ExportRequest 

10 result: gws.ExportResult 

11 progressTotal: int = 1 

12 progressStep: int = 0 

13 progressPercent: int = 0 

14 

15 @classmethod 

16 def run(cls, root: gws.Root, job: gws.Job): 

17 request = gws.u.unserialize_from_path(job.payload.get('requestPath')) 

18 w = cls(root, job.user, job, request) 

19 w.work() 

20 

21 def __init__(self, root: gws.Root, user: gws.User, job: Optional[gws.Job], request: gws.ExportRequest): 

22 super().__init__(root, user, job) 

23 self.request = request 

24 self.result = gws.ExportResult( 

25 path='', 

26 mime='', 

27 numFiles=0, 

28 numFeaturesTotal=0, 

29 numFeaturesExported=0, 

30 errors=[], 

31 ) 

32 

33 def work(self): 

34 self.project = cast(gws.Project, self.user.require(self.request.projectUid, gws.ext.object.project)) 

35 

36 exporter = self.root.app.exporterMgr.get_exporter( 

37 [self.project, self.root.app], 

38 self.request.exporterUid, 

39 self.user, 

40 ) 

41 if not exporter: 

42 raise gws.NotFoundError('exporter not found') 

43 

44 # load + features + write 

45 self.progressTotal = 1 + len(self.request.features or []) + 1 

46 self.update_job(numSteps=100) 

47 

48 features = self.load_features() 

49 self.notify('load') 

50 

51 ea = gws.ExportArgs( 

52 exporter=exporter, 

53 features=features, 

54 shape=self.request.shape, 

55 project=self.project, 

56 user=self.user, 

57 notify=self.notify, 

58 ) 

59 

60 exporter.run(ea, self.result) 

61 self.update_job(state=gws.JobState.complete, result=self.result) 

62 

63 def load_features(self): 

64 if not self.request.features: 

65 return [] 

66 

67 self.result.numFeaturesTotal = len(self.request.features) 

68 

69 models: dict[str, gws.Model] = {} 

70 uid_map: dict[str, set[str]] = {} 

71 fs_map: dict[str, gws.Feature] = {} 

72 

73 mc = gws.ModelContext(op=gws.ModelOperation.export, user=self.user, project=self.project) 

74 

75 for fp in self.request.features: 

76 model_uid = fp.modelUid 

77 feature_uid = fp.uid 

78 

79 model = models.get(model_uid) 

80 if not model: 

81 model = self.root.app.modelMgr.get_model(model_uid, self.user) 

82 if not model: 

83 gws.log.warning(f'model not found: {model_uid}') 

84 continue 

85 models[model_uid] = model 

86 

87 guid = gws.u.join_uid(model_uid, feature_uid) 

88 es = model.exportStrategy or gws.FeatureExportStrategy.load 

89 if es == gws.FeatureExportStrategy.client: 

90 fs_map[guid] = model.feature_from_props(fp, mc) 

91 else: 

92 uid_map.setdefault(model_uid, set()).add(feature_uid) 

93 

94 for model_uid, feature_uids in uid_map.items(): 

95 model = models[model_uid] 

96 fs = model.get_features(feature_uids, mc) 

97 for f in fs: 

98 guid = gws.u.join_uid(model_uid, f.uid()) 

99 fs_map[guid] = f 

100 

101 fs = [] 

102 

103 for fp in self.request.features: 

104 guid = gws.u.join_uid(fp.modelUid, fp.uid) 

105 f = fs_map.get(guid) 

106 if not f: 

107 gws.log.warning(f'feature not found: {guid}') 

108 continue 

109 fs.append(f) 

110 

111 return fs 

112 

113 def notify(self, event, details=None): 

114 job = self.get_job() 

115 if not job: 

116 return 

117 self.progressStep += 1 

118 p = int(self.progressStep / self.progressTotal * 100) 

119 if p > self.progressPercent: 

120 self.progressPercent = p 

121 self.update_job(numSteps=100, step=self.progressPercent)