@@ -4595,36 +4595,28 @@ def get_projects(
45954595 Generator[ProjectDict, None, None]: Queried projects.
45964596
45974597 """
4598- if fields is None :
4599- fields = self .get_default_fields_for_type ("project" )
4600-
4601- fields = set (fields )
4602-
4603- use_rest = self ._should_use_rest_project (fields )
4604- use_graphql = self ._should_use_graphql_project (fields )
4605- if not use_rest :
4606- yield from self ._get_graphql_projects (
4607- active , library , fields , own_attributes
4608- )
4609- return
4598+ if fields is not None :
4599+ fields = set (fields )
46104600
4611- if use_graphql :
4612- for graphql_project in self ._get_graphql_projects (
4601+ graphql_fields , use_rest = self ._get_project_graphql_fields (fields )
4602+ projects_by_name = {}
4603+ if graphql_fields :
4604+ projects = list (self ._get_graphql_projects (
46134605 active ,
46144606 library ,
4615- fields = { "name" , "productTypes" } ,
4607+ fields = graphql_fields ,
46164608 own_attributes = own_attributes ,
4617- ):
4618- project = self .get_project (graphql_project ["name" ])
4619- if own_attributes :
4620- fill_own_attribs (project )
4621- project ["productTypes" ] = graphql_project ["productTypes" ]
4622- yield project
4623- return
4609+ ))
4610+ if not use_rest :
4611+ yield from projects
4612+ return
4613+ projects_by_name = {p ["name" ]: p for p in projects }
46244614
46254615 for project in self .get_rest_projects (active , library ):
4626- if own_attributes :
4627- fill_own_attribs (project )
4616+ name = project ["name" ]
4617+ graphql_p = projects_by_name .get (name )
4618+ if graphql_p :
4619+ project ["productTypes" ] = graphql_p ["productTypes" ]
46284620 yield project
46294621
46304622 def get_project (
@@ -4647,87 +4639,58 @@ def get_project(
46474639 if project was not found.
46484640
46494641 """
4650- if fields is None :
4651- fields = self .get_default_fields_for_type ("project" )
4652-
4653- fields = set (fields )
4642+ if fields is not None :
4643+ fields = set (fields )
46544644
4655- use_rest = self ._should_use_rest_project (fields )
4656- use_graphql = self . _should_use_graphql_project ( fields )
4657- if not use_rest :
4658- for project in self ._get_graphql_projects (
4645+ graphql_fields , use_rest = self ._get_project_graphql_fields (fields )
4646+ graphql_project = None
4647+ if graphql_fields :
4648+ graphql_project = next ( self ._get_graphql_projects (
46594649 None ,
46604650 None ,
4661- fields = fields ,
4651+ fields = graphql_fields ,
46624652 own_attributes = own_attributes ,
4663- project_name = project_name ,
4664- ):
4665- return project
4666- return None
4653+ ), None )
4654+ if not graphql_project or not use_rest :
4655+ return graphql_project
46674656
4668- p_by_name = {}
4669- if use_graphql :
4670- p_by_name = {
4671- p ["name" ]: p
4672- for p in self ._get_graphql_projects (
4673- None ,
4674- None ,
4675- fields = {"name" , "productTypes" },
4676- own_attributes = own_attributes ,
4677- project_name = project_name ,
4678- )
4679- }
4680- for project in self .get_rest_projects (None , None ):
4681- if own_attributes :
4682- fill_own_attribs (project )
4683- graphql_p = p_by_name .get (project ["name" ])
4684- if graphql_p :
4685- project ["productTypes" ] = graphql_p ["productTypes" ]
4686- return project
4687- return None
4657+ project = self .get_rest_project (project_name )
4658+ if own_attributes :
4659+ fill_own_attribs (project )
4660+ if graphql_project :
4661+ project ["productTypes" ] = graphql_project ["productTypes" ]
4662+ return project
46884663
4689- def _should_use_rest_project (
4690- self , fields : Optional [Iterable [str ]] = None
4691- ) -> bool :
4664+ def _get_project_graphql_fields (
4665+ self , fields : Optional [Set [str ]]
4666+ ) -> Tuple [ Set [ str ], bool ] :
46924667 """Fetch of project must be done using REST endpoint.
46934668
46944669 Returns:
4695- bool: REST endpoint must be used to get requested fields.
4670+ set[str]: GraphQl fields.
46964671
46974672 """
4698- maj_v , min_v , patch_v , _ , _ = self .server_version_tuple
4699- # Up to 1.10.0 some project data were not available in GraphQl.
4700- # - 'config', 'tags', 'linkTypes' and 'statuses' at all
4701- # - 'taskTypes', 'folderTypes' with only limited data
4702- if (maj_v , min_v , patch_v ) > (1 , 10 , 0 ):
4703- return False
4704-
4705- for field in fields :
4706- if (
4707- field .startswith ("config" )
4708- or field .startswith ("folderTypes" )
4709- or field .startswith ("taskTypes" )
4710- or field .startswith ("linkTypes" )
4711- or field .startswith ("statuses" )
4712- or field .startswith ("tags" )
4713- ):
4714- return True
4715- return False
4716-
4717- def _should_use_graphql_project (
4718- self , fields : Optional [Iterable [str ]] = None
4719- ) -> bool :
4720- """Fetch of project must be done using REST endpoint.
4721-
4722- Returns:
4723- bool: REST endpoint must be used to get requested fields.
4673+ if fields is None :
4674+ return set (), True
47244675
4725- """
4676+ has_product_types = False
4677+ graphql_fields = set ()
47264678 for field in fields :
47274679 # Product types are available only in GraphQl
47284680 if field .startswith ("productTypes" ):
4729- return True
4730- return False
4681+ has_product_types = True
4682+ graphql_fields .add (field )
4683+
4684+ if not has_product_types :
4685+ return set (), True
4686+
4687+ inters = fields & {"name" , "code" , "active" , "library" }
4688+ remainders = fields - (inters | graphql_fields )
4689+ if remainders :
4690+ graphql_fields .add ("name" )
4691+ return graphql_fields , True
4692+ graphql_fields |= inters
4693+ return graphql_fields , False
47314694
47324695 def _fill_project_entity_data (self , project : Dict [str , Any ]) -> None :
47334696 # Add fake scope to statuses if not available
0 commit comments