22import logging
33import xml .etree .ElementTree as ET
44from pathlib import Path
5- from typing import Optional
5+ from typing import Any , Dict , List , Optional , Union
66
77from somesy .core .models import Person
88from somesy .core .writer import FieldKeyMapping , ProjectMetadataWriter
99
1010from . import POM_ROOT_ATRS , POM_URL
1111from .xmlproxy import XMLProxy
1212
13- ET .register_namespace ("pom" , POM_URL ) # globally register xml namespace for POM
1413logger = logging .getLogger ("somesy" )
1514
1615
@@ -30,10 +29,12 @@ def __init__(
3029 See [somesy.core.writer.ProjectMetadataWriter.__init__][].
3130 """
3231 mappings : FieldKeyMapping = {
33- "year" : ["inceptionYear" ],
32+ # "year": ["inceptionYear"], # not supported by somesy + does not really change
33+ # "project_slug": ["artifactId"], # not supported by somesy for sync
3434 "license" : ["licenses" , "license" ],
3535 "homepage" : ["url" ],
36- "project_slug" : ["artifactId" ],
36+ "repository" : ["scm" ],
37+ "documentation" : ["distributionManagement" , "site" ],
3738 "authors" : ["developers" , "developer" ],
3839 "contributors" : ["contributors" , "contributor" ],
3940 }
@@ -45,10 +46,11 @@ def _init_new_file(self):
4546 """Initialize new pom.xml file."""
4647 pom = XMLProxy (ET .Element ("project" , POM_ROOT_ATRS ))
4748 pom ["properties" ] = {"info.versionScheme" : "semver-spec" }
48- pom .write (self .path , default_namespace = POM_URL )
49+ pom .write (self .path )
4950
5051 def _load (self ):
5152 """Load the POM file."""
53+ ET .register_namespace ("" , POM_URL ) # register POM as default xml namespace
5254 self ._data = XMLProxy .parse (self .path , default_namespace = POM_URL )
5355
5456 def _validate (self ):
@@ -57,30 +59,158 @@ def _validate(self):
5759
5860 def save (self , path : Optional [Path ] = None ) -> None :
5961 """Save the POM DOM to a file."""
60- path = path or self .path
61- self ._data .write (path )
62+ self ._data .write (path or self .path , default_namespace = None )
63+
64+ def _get_property (
65+ self ,
66+ key : Union [str , List [str ]],
67+ * ,
68+ only_first : bool = False ,
69+ remove : bool = False ,
70+ ) -> Optional [Any ]:
71+ elem = super ()._get_property (key , only_first = only_first , remove = remove )
72+ if elem is not None :
73+ if isinstance (elem , list ):
74+ return [e .to_jsonlike () for e in elem ]
75+ else :
76+ return elem .to_jsonlike ()
77+ return None
6278
6379 @staticmethod
6480 def _from_person (person : Person ):
65- """Convert project metadata person object to cff dict for person format."""
66- ret = {}
67- person_id = person .orcid or person .to_name_email_string ()
81+ """Convert person object to dict for POM XML person format."""
82+ ret : Dict [ str , Any ] = {}
83+ person_id = str ( person .orcid ) or person .to_name_email_string ()
6884 ret ["id" ] = person_id
69- ret ["name" ] = person .name
85+ ret ["name" ] = person .full_name
7086 ret ["email" ] = person .email
7187 if person .orcid :
72- ret ["url" ] = person .orcid
88+ ret ["url" ] = str ( person .orcid )
7389 if person .contribution_types :
74- ret ["roles" ] = dict (role = person .contribution_types )
90+ ret ["roles" ] = dict (role = [ c . value for c in person .contribution_types ] )
7591 return ret
7692
7793 @staticmethod
7894 def _to_person (person_obj ) -> Person :
79- """Parse CFF Person to a somesy Person."""
95+ """Parse POM XML person to a somesy Person."""
96+ print (person_obj )
97+ names = person_obj ["name" ].split ()
98+ gnames = " " .join (names [:- 1 ])
99+ fname = names [- 1 ]
100+ email = person_obj ["email" ]
101+ url = person_obj .get ("url" )
102+ maybe_orcid = url if url .find ("orcid.org" ) >= 0 else None
103+ if roles := person_obj .get ("roles" ):
104+ contr = roles ["role" ]
105+ else :
106+ contr = None
107+
80108 return Person (
81- name = person_obj ["name" ],
82- email = person_obj ["email" ],
83- orcid = person_obj ["orcid" ],
84- contribution_types = person_obj ["roles" ]["role" ],
109+ given_names = gnames ,
110+ family_names = fname ,
111+ email = email ,
112+ orcid = maybe_orcid ,
113+ contribution_types = contr ,
85114 )
86- raise NotImplementedError
115+
116+ # no search keywords supported in POM
117+ @property
118+ def keywords (self ) -> Optional [List [str ]]:
119+ """Return the keywords of the project."""
120+ pass
121+
122+ @keywords .setter
123+ def keywords (self , keywords : List [str ]) -> None :
124+ """Set the keywords of the project."""
125+ pass
126+
127+ # authors must be a list
128+ @property
129+ def authors (self ):
130+ """Return the authors of the project."""
131+ authors = self ._get_property (self ._get_key ("authors" ))
132+ return authors if isinstance (authors , list ) else [authors ]
133+
134+ @authors .setter
135+ def authors (self , authors : List [Person ]) -> None :
136+ """Set the authors of the project."""
137+ authors = [self ._from_person (c ) for c in authors ]
138+ self ._set_property (self ._get_key ("authors" ), authors )
139+
140+ # contributors must be a list
141+ @property
142+ def contributors (self ):
143+ """Return the contributors of the project."""
144+ contr = self ._get_property (self ._get_key ("contributors" ))
145+ if contr is None :
146+ return []
147+ return contr if isinstance (contr , list ) else [contr ]
148+
149+ @contributors .setter
150+ def contributors (self , contributors : List [Person ]) -> None :
151+ """Set the contributors of the project."""
152+ contr = [self ._from_person (c ) for c in contributors ]
153+ self ._set_property (self ._get_key ("contributors" ), contr )
154+
155+ # no maintainers supported im POM, only developers and contributors
156+ @property
157+ def maintainers (self ):
158+ """Return the maintainers of the project."""
159+ return []
160+
161+ @maintainers .setter
162+ def maintainers (self , maintainers : List [Person ]) -> None :
163+ """Set the maintainers of the project."""
164+ pass
165+
166+ # only one project license supported in somesy (POM can have many)
167+ @property
168+ def license (self ) -> Optional [str ]:
169+ """Return the license of the project."""
170+ lic = self ._get_property (self ._get_key ("license" ), only_first = True )
171+ return lic .get ("name" ) if lic is not None else None
172+
173+ @license .setter
174+ def license (self , license : Optional [str ]) -> None :
175+ """Set the license of the project."""
176+ self ._set_property (
177+ self ._get_key ("license" ), dict (name = license , distribution = "repo" )
178+ )
179+
180+ @property
181+ def repository (self ) -> Optional [Union [str , dict ]]:
182+ """Return the repository url of the project."""
183+ repo = super ().repository
184+ if isinstance (repo , str ):
185+ return repo
186+ return repo .get ("url" ) if repo is not None else None
187+
188+ @repository .setter
189+ def repository (self , value : Optional [Union [str , dict ]]) -> None :
190+ """Set the repository url of the project."""
191+ self ._set_property (
192+ self ._get_key ("repository" ), dict (name = "git repository" , url = value )
193+ )
194+
195+ @property
196+ def documentation (self ) -> Optional [Union [str , dict ]]:
197+ """Return the documentation url of the project."""
198+ docs = super ().documentation
199+ if isinstance (docs , str ):
200+ return docs
201+ return docs .get ("url" ) if docs is not None else None
202+
203+ @documentation .setter
204+ def documentation (self , value : Optional [Union [str , dict ]]) -> None :
205+ """Set the documentation url of the project."""
206+ self ._set_property (
207+ self ._get_key ("documentation" ), dict (name = "documentation site" , url = value )
208+ )
209+
210+ def sync (self , metadata ) -> None :
211+ """Sync codemeta.json with project metadata.
212+
213+ Use existing sync function from ProjectMetadataWriter but update repository and contributors.
214+ """
215+ super ().sync (metadata )
216+ self .contributors = self ._sync_person_list (self .contributors , metadata .people )
0 commit comments