Skip to content

Commit 544f82a

Browse files
committed
Provide validate API, added validate example, 0.24.0
1 parent 90dec0a commit 544f82a

13 files changed

+895
-30
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.23.0
2+
current_version = 0.24.0
33
commit = True
44
tag = True
55

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88

99
SPDX-License-Identifier: MIT
1010

11-
version="0.23.0"
11+
version="0.24.0"
1212

1313
What's New?
1414
===========
1515

16-
0.23.0 16-Aug-2023
16+
0.24.0 16-Aug-2023
1717
* tested with Python 3.11.4 - worked OOTB. Now developing using 3.11.4 - won't be back-tested with older Pythons but should work back to 3.9 at least.
1818

19-
0.23.0 4-May-2023
19+
0.24.0 4-May-2023
2020
* Deprecated RM load_folders() - use find_folder() instead.
2121
* Added RM create_folder() - this doesn't require doing a forced reload of all folders, because it inserts the new folder into the internal info about folders
2222
* Added example dn_simple_createfolderpath.py - allows exercising the create_folders() function

elmclient/__meta__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
app = 'elmoslcquery'
1111
description = 'Commandline OSLC query for ELM'
12-
version = '0.23.0'
12+
version = '0.24.0'
1313
license = 'MIT'
1414
author_name = 'Ian Barnard'
1515
author_mail = '[email protected]'

elmclient/_app.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
from . import oslcqueryapi
1414
from . import utils
1515
from . import httpops
16+
from . import _validate
1617

1718
logger = logging.getLogger(__name__)
1819

1920
#################################################################################################
2021
# a generic jazz application
2122

22-
class _App( httpops.HttpOperations_Mixin ):
23+
class _App( httpops.HttpOperations_Mixin, _validate.Validate_Mixin ):
2324
'A generic Jazz application'
2425
domain = 'UNSPECIFIED APP DOMAIN'
2526
project_class = None

elmclient/_queryparser.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
# For DNG You can refer to a foldername using e.g. $"folder name" - this gets converted to the URI of the folder in <> NOT EXTENSIVELY TESTED!
3333
# You can refer to a user name using e.g. @"user name" - this gets converted to the server-specific URI of the user
3434

35-
_core_oslc_grammar = """
35+
_core_oslc_grammar = r"""
3636
?compound_term : simple_term
3737
| simple_term boolean_op compound_term -> do_oslcand
3838
@@ -77,6 +77,7 @@
7777
| urioffoldername
7878
| uriofuser
7979
| uriofmodule
80+
| uriofconfig
8081
8182
valueidentifier : ( ( URI_REF_ESC | NAME | "'" SPACYNAME "'" ) ":" )? NAME
8283
| "'" SPACYNAME "'"
@@ -90,6 +91,8 @@
9091
9192
urioffoldername : "$" string_esc
9293
94+
uriofconfig : "#" string_esc
95+
9396
uriofuser : "@" string_esc
9497
9598
uriofmodule : "^" string_esc
@@ -174,6 +177,7 @@ def __init__(self,resolverobject):
174177
self.mapping_users = {} # contains both: key name->uri and key uri->name (uris and names never overlap)
175178
self.mapping_modules = {} # contains both: key name->uri and key uri->name (uris and names never overlap)
176179
self.mapping_projects = {} # contains both: key name->uri and key uri->name (uris and names never overlap)
180+
self.mapping_configs = {} # contains both: key name->uri and key uri->name (uris and names never overlap)
177181

178182
def where_expression(self, s):
179183
logger.debug( f"where_expression {s=}" )
@@ -265,7 +269,7 @@ def term(self, s):
265269
else:
266270
t1 = type(value)
267271
logger.info( f"t1 {value} {t1=}" )
268-
if isinstance(value, str) and not value.startswith('"') and not value.startswith("'") and ':' not in value and not re.match("\d",value):
272+
if isinstance(value, str) and not value.startswith('"') and not value.startswith("'") and ':' not in value and not re.match(r"\d",value):
269273
# this is a valueidentifier - try to resolve it as an enum in the context of identifier
270274
if self.resolverobject.resolve_enum_name_to_uri is not None:
271275
result = self.resolverobject.resolve_enum_name_to_uri(value, identifier)
@@ -371,6 +375,21 @@ def uriofmodule(self,s):
371375
raise Exception( "This application doesn't support module names!" )
372376
return result
373377

378+
def uriofconfig(self,s):
379+
logger.info( f"uriofconfig {s=}" )
380+
name=s[0].strip('"')
381+
if self.resolverobject.resolve_configname_to_uri is not None:
382+
uri = self.resolverobject.resolve_configname_to_uri(name)
383+
if uri is None:
384+
raise Exception( f"Config {name} not found!" )
385+
logger.info( f"uriofconfig {uri=}" )
386+
self.mapping_configs[name]=uri
387+
self.mapping_configs[uri]=name
388+
result = "<"+uri+">"
389+
else:
390+
raise Exception( "This application doesn't support resolving configuration names!" )
391+
return result
392+
374393
# def uriofproject(self,s):
375394
# logger.info( f"uriofproject {s=}" )
376395
# name=s[0].strip('"')
@@ -536,7 +555,7 @@ def scoped_term(self, s):
536555
SPACYNAME : /[a-zA-Z0-9_][^']*/
537556
"""
538557

539-
_orderby_grammar = """
558+
_orderby_grammar = r"""
540559
sort_terms : sort_term ("," sort_term)*
541560
sort_term : scoped_sort_terms | signedterm
542561
signedterm : SIGN ( dottedname | identifier )

elmclient/_rm.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,23 @@ def resolve_modulename_to_uri( self, modulename ):
859859
logger.info( f"rmtu {result=}" )
860860
return result
861861

862+
# def resolve_configname_to_uri( self, configname ):
863+
# configname syntax is domain/project/component/config
864+
# for example (remove the') 'rm:rm23/rm_optin_p1/rm_optin_p1 comp2/rm_optin_p1 comp2 Initial Stream'
865+
# # get the query capability base URL
866+
# qcbase = self.get_query_capability_uri("oslc_rm:Requirement")
867+
# results = self.execute_oslc_query( qcbase, whereterms=[['and', ['dcterms:title','=',f'"{modulename}"'],['rdm_types:ArtifactFormat','=','jazz_rm:Module']]], prefixes={rdfxml.RDF_DEFAULT_PREFIX["dcterms"]:'dcterms',rdfxml.RDF_DEFAULT_PREFIX["rdm_types"]:'rdm_types',rdfxml.RDF_DEFAULT_PREFIX["jazz_rm"]:'jazz_rm'})
868+
# logger.debug( f"resolve_modulename_to_uri {results=}" )
869+
# if len( results.keys() ) == 0:
870+
# result = None
871+
# else:
872+
# if len( results.keys() ) > 1:
873+
# raise Exception( f"More than one module named {modulename}!" )
874+
# result = list(results.keys())[0]
875+
# logger.info( f"rmtu {result=}" )
876+
# return result
877+
878+
862879
def resolve_uri_to_reqid( self, requri ):
863880
pass
864881

elmclient/_validate.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
##
3+
## © Copyright 2021- IBM Inc. All rights reserved
4+
# SPDX-License-Identifier: MIT
5+
##
6+
7+
# This mixin implements the validate API (will be used on each app that supports validate)
8+
# ref https://jazz.net/rm/doc/scenarios
9+
10+
import codecs
11+
import html.parser
12+
import http
13+
import inspect
14+
import json
15+
import logging
16+
import lxml.etree as ET
17+
import re
18+
import time
19+
import urllib
20+
21+
import requests
22+
import tqdm
23+
24+
from elmclient import rdfxml
25+
26+
logger = logging.getLogger(__name__)
27+
28+
29+
class Validate_Mixin():
30+
def listFeeds( self ):
31+
valuri = self.reluri( 'trs_feed_validation/feeds' )
32+
# print( f"{valuri=}" )
33+
results = self.execute_get_json( valuri, headers={'Accept': 'application/json' } )
34+
#
35+
# print( f"{results=}" )
36+
return results
37+
38+
def validate( self, feedid, *, repair=False, resetIncrementalData=False, full=False ):
39+
valuri = self.reluri( 'trs_feed_validation/validate' )
40+
rep = 'true' if repair else 'false'
41+
res = 'true' if resetIncrementalData else 'false'
42+
ful = 'true' if full else 'false'
43+
response = self.execute_post_content( valuri, params={'id': feedid,'repair': rep,'resetIncrementData': res,'full': ful } )
44+
# print( f"{response=}" )
45+
46+
# get the location
47+
location = response.headers.get('Location')
48+
49+
# check for 202 and location
50+
if response.status_code == 202 and location is not None:
51+
print( f"Polling tracker at {location}" )
52+
# wait for the tracker to finished
53+
result = self.wait_for_tracker( location, interval=1.0, progressbar=True, msg=f"Validating feed {feedid}",useJson=True,returnFinal=True)
54+
# TODO: success result is now the xml of the verdict
55+
# result None is a success!
56+
logger.info( f"1 {result=}" )
57+
return result
58+
else:
59+
raise Exception( f"Validate data source {id} failed!" )
60+

0 commit comments

Comments
 (0)