Skip to content
This repository was archived by the owner on Nov 22, 2024. It is now read-only.

Commit e588f6b

Browse files
committed
cleaner sanitize code for keywords, dashes, at-symbols. Cleaner API Exception returns. Added unified find() call to reduce code
1 parent abcdcee commit e588f6b

3 files changed

Lines changed: 99 additions & 62 deletions

File tree

CloudFlare/cloudflare.py

Lines changed: 86 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -700,37 +700,52 @@ def __repr__(self):
700700
def get(self, identifier1=None, identifier2=None, identifier3=None, identifier4=None, params=None, data=None):
701701
""" Cloudflare v4 API"""
702702

703-
if getattr(self, '_content_type', False):
704-
return self._do('GET', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
705-
return self._do('GET', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
703+
try:
704+
if getattr(self, '_content_type', False):
705+
return self._do('GET', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
706+
return self._do('GET', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
707+
except CloudFlareAPIError as e:
708+
raise CloudFlareAPIError(e=e) from None
706709

707710
def patch(self, identifier1=None, identifier2=None, identifier3=None, identifier4=None, params=None, data=None):
708711
""" Cloudflare v4 API"""
709712

710-
if getattr(self, '_content_type', False):
711-
return self._do('PATCH', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
712-
return self._do('PATCH', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
713+
try:
714+
if getattr(self, '_content_type', False):
715+
return self._do('PATCH', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
716+
return self._do('PATCH', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
717+
except CloudFlareAPIError as e:
718+
raise CloudFlareAPIError(e=e) from None
713719

714720
def post(self, identifier1=None, identifier2=None, identifier3=None, identifier4=None, params=None, data=None, files=None):
715721
""" Cloudflare v4 API"""
716722

717-
if getattr(self, '_content_type', False):
718-
return self._do('POST', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files, self._content_type)
719-
return self._do('POST', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files)
723+
try:
724+
if getattr(self, '_content_type', False):
725+
return self._do('POST', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files, self._content_type)
726+
return self._do('POST', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files)
727+
except CloudFlareAPIError as e:
728+
raise CloudFlareAPIError(e=e) from None
720729

721730
def put(self, identifier1=None, identifier2=None, identifier3=None, identifier4=None, params=None, data=None, files=None):
722731
""" Cloudflare v4 API"""
723732

724-
if getattr(self, '_content_type', False):
725-
return self._do('PUT', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files, self._content_type)
726-
return self._do('PUT', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files)
733+
try:
734+
if getattr(self, '_content_type', False):
735+
return self._do('PUT', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files, self._content_type)
736+
return self._do('PUT', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files)
737+
except CloudFlareAPIError as e:
738+
raise CloudFlareAPIError(e=e) from None
727739

728740
def delete(self, identifier1=None, identifier2=None, identifier3=None, identifier4=None, params=None, data=None):
729741
""" Cloudflare v4 API"""
730742

731-
if getattr(self, '_content_type', False):
732-
return self._do('DELETE', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
733-
return self._do('DELETE', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
743+
try:
744+
if getattr(self, '_content_type', False):
745+
return self._do('DELETE', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
746+
return self._do('DELETE', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
747+
except CloudFlareAPIError as e:
748+
raise CloudFlareAPIError(e=e) from None
734749

735750
class _CFbaseUnused(_CFbase):
736751
""" Cloudflare v4 API"""
@@ -754,30 +769,42 @@ def __init__(self, base, parts, content_type):
754769
def patch(self, identifier1=None, identifier2=None, identifier3=None, identifier4=None, params=None, data=None):
755770
""" Cloudflare v4 API"""
756771

757-
if getattr(self, '_content_type', False):
758-
return self._base.do_not_available('PATCH', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
759-
return self._base.do_not_available('PATCH', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
772+
try:
773+
if getattr(self, '_content_type', False):
774+
return self._base.do_not_available('PATCH', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
775+
return self._base.do_not_available('PATCH', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
776+
except CloudFlareAPIError as e:
777+
raise CloudFlareAPIError(e=e) from None
760778

761779
def post(self, identifier1=None, identifier2=None, identifier3=None, identifier4=None, params=None, data=None, files=None):
762780
""" Cloudflare v4 API"""
763781

764-
if getattr(self, '_content_type', False):
765-
return self._base.do_not_available('POST', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files, self._content_type)
766-
return self._base.do_not_available('POST', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files)
782+
try:
783+
if getattr(self, '_content_type', False):
784+
return self._base.do_not_available('POST', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files, self._content_type)
785+
return self._base.do_not_available('POST', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, files)
786+
except CloudFlareAPIError as e:
787+
raise CloudFlareAPIError(e=e) from None
767788

768789
def put(self, identifier1=None, identifier2=None, identifier3=None, identifier4=None, params=None, data=None, files=None):
769790
""" Cloudflare v4 API"""
770791

771-
if getattr(self, '_content_type', False):
772-
return self._base.do_not_available('PUT', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
773-
return self._base.do_not_available('PUT', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
792+
try:
793+
if getattr(self, '_content_type', False):
794+
return self._base.do_not_available('PUT', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
795+
return self._base.do_not_available('PUT', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
796+
except CloudFlareAPIError as e:
797+
raise CloudFlareAPIError(e=e) from None
774798

775799
def delete(self, identifier1=None, identifier2=None, identifier3=None, identifier4=None, params=None, data=None):
776800
""" Cloudflare v4 API"""
777801

778-
if getattr(self, '_content_type', False):
779-
return self._base.do_not_available('DELETE', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
780-
return self._base.do_not_available('DELETE', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
802+
try:
803+
if getattr(self, '_content_type', False):
804+
return self._base.do_not_available('DELETE', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data, self._content_type)
805+
return self._base.do_not_available('DELETE', self._parts, [identifier1, identifier2, identifier3, identifier4], params, data)
806+
except CloudFlareAPIError as e:
807+
raise CloudFlareAPIError(e=e) from None
781808

782809
class _CFbaseAuth(_CFbase):
783810
""" Cloudflare v4 API"""
@@ -809,6 +836,23 @@ def __init__(self, base, parts, content_type):
809836
self._do = self._base.do_certauth
810837
self._valid = True
811838

839+
@classmethod
840+
def sanitize_verb(cls, v):
841+
""" sanitize_verb """
842+
# keywords are also changed to have underscore appended so it can used with Python code
843+
if keyword.iskeyword(v):
844+
v = v + '_'
845+
# AI functions introduce '@' symbol - i.e .../@cf/... they are replaced with at_
846+
if '@' == v[0]:
847+
v = 'at_' + v[1:]
848+
# AI functions introduce '.' symbol - i.e 1.0 they are replaced with underscore
849+
if '.' in v:
850+
v = v.replace('.','_')
851+
# dashes (vs underscores) cause issues in Python and other languages. they are replaced with underscores
852+
if '-' in v:
853+
v = v.replace('-','_')
854+
return v
855+
812856
def add(self, t, p1, p2=None, p3=None, p4=None, p5=None, content_type=None):
813857
""" add api call to class"""
814858

@@ -830,10 +874,7 @@ def add(self, t, p1, p2=None, p3=None, p4=None, p5=None, content_type=None):
830874
element = None
831875
for element in a[0:-1]:
832876
try:
833-
if '-' in element:
834-
branch = getattr(branch, element.replace('-','_'))
835-
else:
836-
branch = getattr(branch, element)
877+
branch = getattr(branch, CloudFlare.sanitize_verb(element))
837878
except AttributeError:
838879
# missing path - should never happen unless api_v4 is a busted file
839880
branch = None
@@ -844,15 +885,7 @@ def add(self, t, p1, p2=None, p3=None, p4=None, p5=None, content_type=None):
844885

845886
name = a[-1]
846887
try:
847-
if keyword.iskeyword(name):
848-
# add the keyword appended with an extra underscore so it can used with Python code
849-
f = getattr(branch, name + '_')
850-
else:
851-
if '-' in name:
852-
# dashes (vs underscores) cause issues in Python and other languages
853-
f = getattr(branch, name.replace('-','_'))
854-
else:
855-
f = getattr(branch, name)
888+
branch = getattr(branch, CloudFlare.sanitize_verb(name))
856889
# we only are here becuase the name already exists - don't let it overwrite - should never happen unless api_v4 is a busted file
857890
raise CloudFlareAPIError(0, 'api load: duplicate name found: %s/**%s**' % ('/'.join(a[0:-1]), name))
858891
except AttributeError:
@@ -873,15 +906,19 @@ def add(self, t, p1, p2=None, p3=None, p4=None, p5=None, content_type=None):
873906
# should never happen
874907
raise CloudFlareAPIError(0, 'api load type mismatch')
875908

876-
if keyword.iskeyword(name):
877-
# add the keyword appended with an extra underscore so it can used with Python code
878-
setattr(branch, name + '_', f)
879-
else:
880-
if '-' in name:
881-
# dashes (vs underscores) cause issues in Python and other languages
882-
setattr(branch, name.replace('-','_'), f)
883-
else:
884-
setattr(branch, name, f)
909+
setattr(branch, CloudFlare.sanitize_verb(name), f)
910+
911+
def find(self, cmd):
912+
""" find """
913+
m = self
914+
for verb in cmd.split('/'):
915+
if verb == '' or verb[0] == ':':
916+
continue
917+
try:
918+
m = getattr(m, CloudFlare.sanitize_verb(verb))
919+
except AttributeError:
920+
raise AttributeError('%s: not found' % (verb)) from None
921+
return m
885922

886923
def api_list(self):
887924
""" recursive walk of the api tree returning a list of api calls"""

CloudFlare/exceptions.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,24 @@ def __int__(self):
1616
def __str__(self):
1717
return self.message
1818

19-
def __init__(self, code, message, error_chain=None):
19+
def __init__(self, code=0, message=None, error_chain=None, e=None):
2020
""" errors for Cloudflare API"""
2121

22-
self.evalue = self.CodeMessage(int(code), str(message))
22+
if e and isinstance(e, CloudFlareAPIError):
23+
self.evalue = e.evalue
24+
self.error_chain = e.error_chain
25+
return
26+
27+
self.evalue = CloudFlareError.CodeMessage(int(code), str(message))
2328
self.error_chain = None
2429
if error_chain is not None:
2530
self.error_chain = []
2631
for evalue in error_chain:
27-
self.error_chain.append(
28-
self.CodeMessage(int(evalue['code']), str(evalue['message'])))
32+
if isinstance(evalue, CloudFlareError.CodeMessage):
33+
v = evalue
34+
else:
35+
v = CloudFlareError.CodeMessage(int(evalue['code']), str(evalue['message']))
36+
self.error_chain.append(v)
2937
# self.error_chain.append({'code': self.code, 'message': str(self.message)})
3038
# As we are built off Exception, we need to get our superclass all squared away
3139
# super().__init__(message)

cli4/cli4.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import sys
55
import re
66
import getopt
7-
import keyword
87
import json
98

109
import CloudFlare
@@ -272,14 +271,7 @@ def run_command(cf, method, command, params=None, content=None, files=None):
272271
raise e
273272
else:
274273
try:
275-
if keyword.iskeyword(element):
276-
# a keyword is appended with an extra underscore so it can used with Python code
277-
m = getattr(m, element + '_')
278-
elif '-' in element:
279-
# dashes (vs underscores) cause issues in Python and other languages
280-
m = getattr(m, element.replace('-','_'))
281-
else:
282-
m = getattr(m, element)
274+
m = getattr(m, CloudFlare.CloudFlare.sanitize_verb(element))
283275
cmd.append(element)
284276
except AttributeError as e:
285277
# the verb/element was not found

0 commit comments

Comments
 (0)