From 4071b6a5ac84251a3850b8daac74998d8a4d6ea2 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Sat, 11 Dec 2021 11:04:58 -0500 Subject: [PATCH] 2021-12-11 Fred Gleason * Added a 'Cart' class to the 'rivwebapi' API. * Modified the 'AddCart()', 'ListCart()' and 'ListCarts()' methods to use the 'Cart' class in the 'rivwebapi' API. * Added an 'EditCart()' method to the 'rivwebpyapi' API. Signed-off-by: Fred Gleason --- ChangeLog | 5 + apis/rivwebpyapi/api/rivwebpyapi.py | 233 +++++++++++++++------------ apis/rivwebpyapi/tests/Makefile.am | 1 + apis/rivwebpyapi/tests/add_cart.py | 33 +--- apis/rivwebpyapi/tests/edit_cart.py | 93 +++++++++++ apis/rivwebpyapi/tests/list_cart.py | 33 +--- apis/rivwebpyapi/tests/list_carts.py | 31 +--- 7 files changed, 237 insertions(+), 192 deletions(-) create mode 100755 apis/rivwebpyapi/tests/edit_cart.py diff --git a/ChangeLog b/ChangeLog index f8d1dde3..33718959 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22733,3 +22733,8 @@ * Added a 'RemoveRss()' method to the 'rivwebpyapi' API. 2021-12-09 Fred Gleason * Added a 'PostRss()' method to the 'rivwebpyapi' API. +2021-12-11 Fred Gleason + * Added a 'Cart' class to the 'rivwebapi' API. + * Modified the 'AddCart()', 'ListCart()' and 'ListCarts()' methods + to use the 'Cart' class in the 'rivwebapi' API. + * Added an 'EditCart()' method to the 'rivwebpyapi' API. diff --git a/apis/rivwebpyapi/api/rivwebpyapi.py b/apis/rivwebpyapi/api/rivwebpyapi.py index 83e940bb..4b703836 100755 --- a/apis/rivwebpyapi/api/rivwebpyapi.py +++ b/apis/rivwebpyapi/api/rivwebpyapi.py @@ -38,6 +38,41 @@ AUDIO_FORMAT_MPEG_L3_NATIVE=3 AUDIO_FORMAT_FLAC=4 AUDIO_FORMAT_OGG_VORBIS=5 +# +# Data Schemas +# +CART_FIELDS={ + 'number': 'integer', + 'type': 'string', + 'groupName': 'string', + 'title': 'string', + 'artist': 'string', + 'album': 'string', + 'year': 'integer', + 'label': 'string', + 'client': 'string', + 'agency': 'string', + 'publisher': 'string', + 'composer': 'string', + 'conductor': 'string', + 'userDefined': 'string', + 'usageCode': 'integer', + 'forcedLength': 'string', + 'averageLength': 'string', + 'lengthDeviation': 'string', + 'averageSegueLength': 'string', + 'averageHookLength': 'string', + 'minimumTalkLength': 'string', + 'maximumTalkLength': 'string', + 'cutQuantity': 'integer', + 'lastCutPlayed': 'integer', + 'enforceLength': 'boolean', + 'asyncronous': 'boolean', + 'owner': 'string', + 'metadataDatetime': 'datetime', + 'songId': 'string' +} + class RivWebPyApi_ListHandler(ContentHandler): def __init__(self,base_tag,fields): self.__output=[] @@ -196,6 +231,23 @@ class RivWebPyError(Exception): self.errorString=resp_body self.responseCode=resp_code +class Cart(object): + def __init__(self,values={}): + if(len(values)==0): + self.__values={} + for key in CART_FIELDS: + self.__values[key]=None + else: + self.__values=values + + def values(self): + return self.__values + + def setValues(self,values): + for key in values: + if(key in self.__values.keys()): + self.__values[key]=values[key] + class rivwebpyapi(object): """ Create a 'RivWebPyApi' object for accessing the Web API. @@ -244,7 +296,7 @@ class rivwebpyapi(object): def AddCart(self,group_name,cart_type,cart_number=0): """ Add a new cart to the cart library. Returns the metadata of - the newly created cart (dictionary). + the newly created cart (rivwebpyapi.Cart object). Takes the following arguments: @@ -288,41 +340,10 @@ class rivwebpyapi(object): # # Generate the output dictionary # - fields={ - 'number': 'integer', - 'type': 'string', - 'groupName': 'string', - 'title': 'string', - 'artist': 'string', - 'album': 'string', - 'year': 'integer', - 'label': 'string', - 'client': 'string', - 'agency': 'string', - 'publisher': 'string', - 'composer': 'string', - 'conductor': 'string', - 'userDefined': 'string', - 'usageCode': 'integer', - 'forcedLength': 'string', - 'averageLength': 'string', - 'lengthDeviation': 'string', - 'averageSegueLength': 'string', - 'averageHookLength': 'string', - 'minimumTalkLength': 'string', - 'maximumTalkLength': 'string', - 'cutQuantity': 'integer', - 'lastCutPlayed': 'integer', - 'enforceLength': 'boolean', - 'asyncronous': 'boolean', - 'owner': 'string', - 'metadataDatetime': 'datetime', - 'songId': 'string' - } - handler=RivWebPyApi_ListHandler(base_tag='cart',fields=fields) + handler=RivWebPyApi_ListHandler(base_tag='cart',fields=CART_FIELDS) xml.sax.parseString(r.text,handler) - return handler.output()[0] + return Cart(handler.output()[0]) def AddCut(self,cart_number): """ @@ -648,6 +669,69 @@ class rivwebpyapi(object): if(r.status_code!=requests.codes.ok): self.__throwError(response=r) + def EditCart(self,cart_number,values): + """ + Write metadata changes for an existing cart into the database. + + Takes the following arguments: + + cart_number - The number of the desired cart, in the range + 1 - 999999. + + values - A Cart object containing the desired edits. + """ + + if((cart_number<0)or(cart_number>999999)): + raise ValueError('invalid cart number') + + # + # Build the WebAPI arguments + # + postdata={ + 'COMMAND': '14', + 'LOGIN_NAME': self.__connection_username, + 'PASSWORD': self.__connection_password, + 'CART_NUMBER': str(cart_number) + } + postnames={ + 'number': 'CART_NUMBER', + 'groupName': 'GROUP_NAME', + 'title': 'TITLE', + 'artist': 'ARTIST', + 'album': 'ALBUM', + 'year': 'YEAR', + 'label': 'LABEL', + 'client': 'CLIENT', + 'agency': 'AGENCY', + 'publisher': 'PUBLISHER', + 'composer': 'COMPOSER', + 'conductor': 'CONDUCTOR', + 'userDefined': 'USER_DEFINED', + 'usageCode': 'USAGE_CODE', + 'forcedLength': 'FORCED_LENGTH', + 'enforceLength': 'ENFORCE_LENGTH', + 'asyncronous': 'ASYNCHRONOUS', + 'owner': 'OWNER' + } + for key in values: + if((values[key]!=None)and(key in postnames.keys())): + postdata[postnames[key]]=values[key] + + # + # Execute + # + r=requests.post(self.__connection_url,data=postdata) + if(r.status_code!=requests.codes.ok): + self.__throwError(response=r) + + # + # Generate the output dictionary + # + handler=RivWebPyApi_ListHandler(base_tag='cart',fields=CART_FIELDS) + xml.sax.parseString(r.text,handler) + + return Cart(handler.output()[0]) + def Export(self,filename,cart_number,cut_number,audio_format,channels, sample_rate,bit_rate,quality,start_point,end_point, normalization_level,enable_metadata): @@ -896,7 +980,7 @@ class rivwebpyapi(object): def ListCart(self,cart_number,include_cuts=False): """ Returns the metadata associated with a Rivendell cart - (dictionary). + (rivwebpyapi.Cart object). Takes the following arguments: @@ -933,47 +1017,16 @@ class rivwebpyapi(object): # # Generate the output dictionary # - fields={ - 'number': 'integer', - 'type': 'string', - 'groupName': 'string', - 'title': 'string', - 'artist': 'string', - 'album': 'string', - 'year': 'integer', - 'label': 'string', - 'client': 'string', - 'agency': 'string', - 'publisher': 'string', - 'composer': 'string', - 'conductor': 'string', - 'userDefined': 'string', - 'usageCode': 'integer', - 'forcedLength': 'string', - 'averageLength': 'string', - 'lengthDeviation': 'string', - 'averageSegueLength': 'string', - 'averageHookLength': 'string', - 'minimumTalkLength': 'string', - 'maximumTalkLength': 'string', - 'cutQuantity': 'integer', - 'lastCutPlayed': 'integer', - 'enforceLength': 'boolean', - 'asyncronous': 'boolean', - 'owner': 'string', - 'metadataDatetime': 'datetime', - 'songId': 'string' - } - handler=RivWebPyApi_ListHandler(base_tag='cart',fields=fields) + handler=RivWebPyApi_ListHandler(base_tag='cart',fields=CART_FIELDS) xml.sax.parseString(r.text,handler) - return handler.output()[0] + return Cart(handler.output()[0]) def ListCarts(self,group_name='',filter_string='',cart_type='all', include_cuts=False): """ Returns the metadata associated with a set of Rivendell carts - (list of dictionaries) + (list of rivwebpyapi.Cart objects) Takes the following arguments: @@ -1016,43 +1069,16 @@ class rivwebpyapi(object): self.__throwError(response=r) # - # Generate the output dictionary + # Generate the output # - fields={ - 'number': 'integer', - 'type': 'string', - 'groupName': 'string', - 'title': 'string', - 'artist': 'string', - 'album': 'string', - 'year': 'integer', - 'label': 'string', - 'client': 'string', - 'agency': 'string', - 'publisher': 'string', - 'composer': 'string', - 'conductor': 'string', - 'userDefined': 'string', - 'usageCode': 'integer', - 'forcedLength': 'string', - 'averageLength': 'string', - 'lengthDeviation': 'string', - 'averageSegueLength': 'string', - 'averageHookLength': 'string', - 'minimumTalkLength': 'string', - 'maximumTalkLength': 'string', - 'cutQuantity': 'integer', - 'lastCutPlayed': 'integer', - 'enforceLength': 'boolean', - 'asyncronous': 'boolean', - 'owner': 'string', - 'metadataDatetime': 'datetime', - 'songId': 'string' - } - handler=RivWebPyApi_ListHandler(base_tag='cart',fields=fields) + handler=RivWebPyApi_ListHandler(base_tag='cart',fields=CART_FIELDS) xml.sax.parseString(r.text,handler) + out=handler.output() + ret=[] + for item in out: + ret.append(Cart(item)) - return handler.output() + return ret def ListCartSchedCodes(self,cart_number): """ @@ -1138,6 +1164,7 @@ class rivwebpyapi(object): # # Generate the output dictionary # + fields={ 'cutName': 'string', 'cartNumber': 'integer', diff --git a/apis/rivwebpyapi/tests/Makefile.am b/apis/rivwebpyapi/tests/Makefile.am index 8749cf99..b7dbe08b 100644 --- a/apis/rivwebpyapi/tests/Makefile.am +++ b/apis/rivwebpyapi/tests/Makefile.am @@ -28,6 +28,7 @@ EXTRA_DIST = add_cart.py\ audio_store.py\ delete_audio.py\ delete_log.py\ + edit_cart.py\ export.py\ export_peaks.py\ get_podcast.py\ diff --git a/apis/rivwebpyapi/tests/add_cart.py b/apis/rivwebpyapi/tests/add_cart.py index 5658c45f..f00b4d5f 100755 --- a/apis/rivwebpyapi/tests/add_cart.py +++ b/apis/rivwebpyapi/tests/add_cart.py @@ -85,36 +85,9 @@ except rivwebpyapi.RivWebPyError as err: sys.exit(1) # -# Display the cart list +# Display the new cart # print('ADDED') -print('number: '+str(cart['number'])) -print('type: '+str(cart['type'])) -print('groupName: '+str(cart['groupName'])) -print('title: '+str(cart['title'])) -print('artist: '+str(cart['artist'])) -print('album: '+str(cart['album'])) -print('year: '+str(cart['year'])) -print('label: '+str(cart['label'])) -print('client: '+str(cart['client'])) -print('agency: '+str(cart['agency'])) -print('publisher: '+str(cart['publisher'])) -print('composer: '+str(cart['composer'])) -print('conductor: '+str(cart['conductor'])) -print('userDefined: '+str(cart['userDefined'])) -print('usageCode: '+str(cart['usageCode'])) -print('forcedLength: '+str(cart['forcedLength'])) -print('averageLength: '+str(cart['averageLength'])) -print('lengthDeviation: '+str(cart['lengthDeviation'])) -print('averageSegueLength: '+str(cart['averageSegueLength'])) -print('averageHookLength: '+str(cart['averageHookLength'])) -print('minimumTalkLength: '+str(cart['minimumTalkLength'])) -print('maximumTalkLength: '+str(cart['maximumTalkLength'])) -print('cutQuantity: '+str(cart['cutQuantity'])) -print('lastCutPlayed: '+str(cart['lastCutPlayed'])) -print('enforceLength: '+str(cart['enforceLength'])) -print('asyncronous: '+str(cart['asyncronous'])) -print('owner: '+str(cart['owner'])) -print('metadataDatetime: '+str(cart['metadataDatetime'])) -print('songId: '+str(cart['songId'])) +for key in rivwebpyapi.CART_FIELDS: + print(key+': '+str(cart.values()[key])) print('') diff --git a/apis/rivwebpyapi/tests/edit_cart.py b/apis/rivwebpyapi/tests/edit_cart.py new file mode 100755 index 00000000..5089deee --- /dev/null +++ b/apis/rivwebpyapi/tests/edit_cart.py @@ -0,0 +1,93 @@ +#!%PYTHON_BANGPATH% + +# edit_cart.py +# +# RivWebPyApi test script for Rivendell +# +# Test the EditCart Web API call +# +# (C) Copyright 2021 Fred Gleason +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import getpass +import rivwebpyapi +import sys +def eprint(*args,**kwargs): + print(*args,file=sys.stderr,**kwargs) + +url=''; +username='' +password='' +cart_number=0 +values={} + +# +# Get login parameters +# +usage='list_cart --url= --username= --cart-number= [--set-value== ...] [--password=]' +for arg in sys.argv: + f0=arg.split('=') + key=f0[0] + del f0[0] + value='='.join(f0) + if(value): + if(key=='--url'): + url=value + if(key=='--username'): + username=value + if(key=='--password'): + password=value + if(key=='--cart-number'): + cart_number=int(value) + if(key=='--set-value'): + f1=value.split('=') + key1=f1[0] + del f1[0] + values[key1]='='.join(f1) + +if(not password): + password=getpass.getpass() +if((not url)or(not username)): + print(usage) + sys.exit(1) +if(cart_number==0): + eprint('you must supply "--cart-number"') + sys.exit(1) + +# +# Get the cart list +# +webapi=rivwebpyapi.rivwebpyapi(url=url,username=username,password=password) +cart=rivwebpyapi.Cart() +cart.setValues(values) + +try: + cart=webapi.EditCart(cart_number=cart_number,values=cart.values()) +except rivwebpyapi.RivWebPyError as err: + eprint('*** ERROR ***') + eprint('Response Code: '+str(err.responseCode)) + eprint('ErrorString: '+str(err.errorString)) + eprint('*************') + eprint('') + sys.exit(1) + +# +# Display the modified cart +# +print('MODIFIED') +for key in cart.values(): + print(key+': '+str(cart.values()[key])) +print('') diff --git a/apis/rivwebpyapi/tests/list_cart.py b/apis/rivwebpyapi/tests/list_cart.py index 7bf7ec48..398d7eed 100755 --- a/apis/rivwebpyapi/tests/list_cart.py +++ b/apis/rivwebpyapi/tests/list_cart.py @@ -74,35 +74,8 @@ except rivwebpyapi.RivWebPyError as err: sys.exit(1) # -# Display the cart list +# Display the cart # -print('number: '+str(cart['number'])) -print('type: '+str(cart['type'])) -print('groupName: '+str(cart['groupName'])) -print('title: '+str(cart['title'])) -print('artist: '+str(cart['artist'])) -print('album: '+str(cart['album'])) -print('year: '+str(cart['year'])) -print('label: '+str(cart['label'])) -print('client: '+str(cart['client'])) -print('agency: '+str(cart['agency'])) -print('publisher: '+str(cart['publisher'])) -print('composer: '+str(cart['composer'])) -print('conductor: '+str(cart['conductor'])) -print('userDefined: '+str(cart['userDefined'])) -print('usageCode: '+str(cart['usageCode'])) -print('forcedLength: '+str(cart['forcedLength'])) -print('averageLength: '+str(cart['averageLength'])) -print('lengthDeviation: '+str(cart['lengthDeviation'])) -print('averageSegueLength: '+str(cart['averageSegueLength'])) -print('averageHookLength: '+str(cart['averageHookLength'])) -print('minimumTalkLength: '+str(cart['minimumTalkLength'])) -print('maximumTalkLength: '+str(cart['maximumTalkLength'])) -print('cutQuantity: '+str(cart['cutQuantity'])) -print('lastCutPlayed: '+str(cart['lastCutPlayed'])) -print('enforceLength: '+str(cart['enforceLength'])) -print('asyncronous: '+str(cart['asyncronous'])) -print('owner: '+str(cart['owner'])) -print('metadataDatetime: '+str(cart['metadataDatetime'])) -print('songId: '+str(cart['songId'])) +for key in cart.values(): + print(key+': '+str(cart.values()[key])) print('') diff --git a/apis/rivwebpyapi/tests/list_carts.py b/apis/rivwebpyapi/tests/list_carts.py index 52982a0c..ce1596aa 100755 --- a/apis/rivwebpyapi/tests/list_carts.py +++ b/apis/rivwebpyapi/tests/list_carts.py @@ -85,33 +85,6 @@ except rivwebpyapi.RivWebPyError as err: # Display the cart list # for cart in carts: - print('number: '+str(cart['number'])) - print('type: '+str(cart['type'])) - print('groupName: '+str(cart['groupName'])) - print('title: '+str(cart['title'])) - print('artist: '+str(cart['artist'])) - print('album: '+str(cart['album'])) - print('year: '+str(cart['year'])) - print('label: '+str(cart['label'])) - print('client: '+str(cart['client'])) - print('agency: '+str(cart['agency'])) - print('publisher: '+str(cart['publisher'])) - print('composer: '+str(cart['composer'])) - print('conductor: '+str(cart['conductor'])) - print('userDefined: '+str(cart['userDefined'])) - print('usageCode: '+str(cart['usageCode'])) - print('forcedLength: '+str(cart['forcedLength'])) - print('averageLength: '+str(cart['averageLength'])) - print('lengthDeviation: '+str(cart['lengthDeviation'])) - print('averageSegueLength: '+str(cart['averageSegueLength'])) - print('averageHookLength: '+str(cart['averageHookLength'])) - print('minimumTalkLength: '+str(cart['minimumTalkLength'])) - print('maximumTalkLength: '+str(cart['maximumTalkLength'])) - print('cutQuantity: '+str(cart['cutQuantity'])) - print('lastCutPlayed: '+str(cart['lastCutPlayed'])) - print('enforceLength: '+str(cart['enforceLength'])) - print('asyncronous: '+str(cart['asyncronous'])) - print('owner: '+str(cart['owner'])) - print('metadataDatetime: '+str(cart['metadataDatetime'])) - print('songId: '+str(cart['songId'])) + for key in cart.values(): + print(key+': '+str(cart.values()[key])) print('')