Coverage for gws-app / gws / base / feature / __init__.py: 75%

69 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-03 10:12 +0100

1from typing import Optional 

2 

3import gws 

4import gws.base.shape 

5import gws.lib.style 

6import gws.lib.svg 

7 

8 

9def new( 

10 model: gws.Model, 

11 attributes: Optional[dict] = None, 

12 record: Optional[gws.FeatureRecord] = None, 

13 props: Optional[gws.FeatureProps] = None, 

14) -> gws.Feature: 

15 f = Feature(model) 

16 f.attributes = attributes or {} 

17 f.record = record or gws.FeatureRecord(attributes={}) 

18 f.props = props or gws.FeatureProps(attributes={}) 

19 return f 

20 

21 

22class Feature(gws.Feature): 

23 def __init__(self, model: gws.Model): 

24 self.attributes = {} 

25 self.category = '' 

26 self.cssSelector = '' 

27 self.errors = [] 

28 self.isNew = False 

29 self.model = model 

30 self.views = {} 

31 self.createWithFeatures = [] 

32 self.insertedPrimaryKey = '' 

33 

34 def __repr__(self): 

35 try: 

36 return f'<feature {self.model.uid}:{self.uid()}>' 

37 except Exception: 

38 return f'<feature ?>' 

39 

40 def uid(self): 

41 if not self.model.uidName: 

42 return '' 

43 v = self.attributes.get(self.model.uidName) 

44 if v is not None: 

45 return str(v) 

46 

47 def shape(self): 

48 if self.model.geometryName: 

49 return self.attributes.get(self.model.geometryName) 

50 

51 def get(self, name, default=None): 

52 return self.attributes.get(name, default) 

53 

54 def has(self, name): 

55 return name in self.attributes 

56 

57 def set(self, name, value): 

58 self.attributes[name] = value 

59 return self 

60 

61 def raw(self, name): 

62 return self.record.attributes.get(name) 

63 

64 def render_views(self, templates, **kwargs): 

65 tri = gws.TemplateRenderInput( 

66 args=gws.u.merge( 

67 self.attributes, 

68 kwargs, 

69 feature=self, 

70 ) 

71 ) 

72 for tpl in templates: 

73 view_name = tpl.subject.split('.')[-1] 

74 self.views[view_name] = tpl.render(tri).content 

75 return self 

76 

77 def transform_to(self, crs) -> gws.Feature: 

78 s = self.shape() 

79 if s: 

80 self.attributes[self.model.geometryName] = s.transformed_to(crs) 

81 return self 

82 

83 def to_svg(self, view, label=None, style=None): 

84 s = self.shape() 

85 if not s: 

86 return [] 

87 shape = s.transformed_to(view.bounds.crs) 

88 return gws.lib.svg.shape_to_fragment(shape, view, label, style) 

89 

90 def to_geojson(self, keep_crs=False) -> dict: 

91 d = { 

92 'type': 'Feature', 

93 'properties': { 

94 k: v # noqa 

95 for k, v in self.attributes.items() 

96 if k != self.model.geometryName 

97 }, 

98 } 

99 d['properties']['id'] = self.uid() 

100 s = self.shape() 

101 if s: 

102 d['geometry'] = s.to_geojson(keep_crs=keep_crs) 

103 return d