Skip to content

Commit

Permalink
json config load fix for python 3 and some pep8 cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
vnitinv committed Jul 22, 2016
1 parent 7327510 commit d4416d2
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 37 deletions.
65 changes: 39 additions & 26 deletions lib/jnpr/junos/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ def _in_path(dir):
path = os.path.join(path[0], template)
mtime = os.path.getmtime(path)
with open(path) as f:
# You are trying to decode an object that is already decoded. You have a str,
# there is no need to decode from UTF-8 anymore.
# You are trying to decode an object that is already decoded.
# You have a str, there is no need to decode from UTF-8 anymore.
# open already decodes to Unicode in Python 3 if you open in text mode.
# If you want to open it as bytes, so that you can then decode, you need to open with mode 'rb'.
# If you want to open it as bytes, so that you can then decode,
# you need to open with mode 'rb'.
source = f.read()
return source, path, lambda: mtime == os.path.getmtime(path)

Expand Down Expand Up @@ -220,7 +221,6 @@ def _sshconf_lkup(self):
self._conf_ssh_private_key_file = found.get('identityfile')
return sshconf_path


def display_xml_rpc(self, command, format='xml'):
"""
Executes the CLI command and returns the CLI xml object by default.
Expand All @@ -246,7 +246,6 @@ def display_xml_rpc(self, command, format='xml'):
except:
return "invalid command: " + command


# ------------------------------------------------------------------------
# Template: retrieves a Jinja2 template
# ------------------------------------------------------------------------
Expand Down Expand Up @@ -315,9 +314,16 @@ def bind(self, *vargs, **kvargs):
for fn in vargs:
# bind as instance method, majik.
if sys.version < '3':
self.__dict__[fn.__name__] = types.MethodType(fn, self, self.__class__)
self.__dict__[
fn.__name__] = types.MethodType(
fn,
self,
self.__class__)
else:
self.__dict__[fn.__name__] = types.MethodType(fn, self.__class__)
self.__dict__[
fn.__name__] = types.MethodType(
fn,
self.__class__)
return

# first verify that the names do not conflict with
Expand Down Expand Up @@ -400,10 +406,10 @@ def cli(self, command, format='text', warning=True):
.. note::
You can also use this method to obtain the XML RPC command for a
given CLI command by using the pipe filter ``| display xml rpc``. When
you do this, the return value is the XML RPC command. For example if
you provide as the command ``show version | display xml rpc``, you will
get back the XML Element ``<get-software-information>``.
given CLI command by using the pipe filter ``| display xml rpc``.
When you do this, the return value is the XML RPC command. For
example if you provide as the command ``show version | display xml rpc``,
you will get back the XML Element ``<get-software-information>``.
.. warning::
This function is provided for **DEBUG** purposes only!
Expand Down Expand Up @@ -441,14 +447,13 @@ def cli(self, command, format='text', warning=True):
return rsp[0]
return rsp
except EzErrors.RpcError as ex:
if ex.message is not '':
return "%s: %s" % (ex.message, command)
if str(ex) is not '':
return "%s: %s" % (str(ex), command)
else:
return "invalid command: " + command
except Exception as ex:
return "invalid command: " + command


# ------------------------------------------------------------------------
# facts
# ------------------------------------------------------------------------
Expand All @@ -468,11 +473,13 @@ def facts_refresh(self, exception_on_failure=False):
if exception_on_failure:
raise
warnings.warn('Facts gathering is incomplete. '
'To know the reason call "dev.facts_refresh(exception_on_failure=True)"', RuntimeWarning)
'To know the reason call "dev.facts_refresh(exception_on_failure=True)"',
RuntimeWarning)
return


class Device(_Connection):

"""
Junos Device class.
Expand All @@ -496,14 +503,14 @@ class Device(_Connection):
dev.open() # this will probe before attempting NETCONF connect
"""
ON_JUNOS = platform.system().upper() == 'JUNOS' or platform.release().startswith('JNPR')
ON_JUNOS = platform.system().upper() == 'JUNOS' or \
platform.release().startswith('JNPR')
auto_probe = 0 # default is no auto-probe

# -------------------------------------------------------------------------
# PROPERTIES
# -------------------------------------------------------------------------


# ------------------------------------------------------------------------
# property: transform
# ------------------------------------------------------------------------
Expand Down Expand Up @@ -544,7 +551,7 @@ def __new__(cls, *args, **kwargs):
# __new__() is an instance of the class in which the __new__()
# method is contained (here Device class). Hence calling __init__
# explicitly.
kwargs['host']=args[0] if len(args) else kwargs.get('host')
kwargs['host'] = args[0] if len(args) else kwargs.get('host')
instance.__init__(**kwargs)
return instance
else:
Expand Down Expand Up @@ -643,9 +650,12 @@ def __init__(self, *vargs, **kvargs):
# user can get updated by ssh_config
self._ssh_config = kvargs.get('ssh_config')
# but if user or private key is explicit from call, then use it.
self._auth_user = kvargs.get('user') or self._conf_auth_user or self._auth_user
self._ssh_private_key_file = kvargs.get('ssh_private_key_file') or self._conf_ssh_private_key_file
self._auth_password = kvargs.get('password') or kvargs.get('passwd')
self._auth_user = kvargs.get('user') or self._conf_auth_user or \
self._auth_user
self._ssh_private_key_file = kvargs.get('ssh_private_key_file') \
or self._conf_ssh_private_key_file
self._auth_password = kvargs.get(
'password') or kvargs.get('passwd')

# -----------------------------
# initialize instance variables
Expand Down Expand Up @@ -857,11 +867,14 @@ def execute(self, rpc_cmd, **kvargs):
except RPCError as err:
rsp = JXML.remove_namespaces(err.xml)
# see if this is a permission error
e = EzErrors.PermissionError if rsp.findtext('error-message') == 'permission denied' else EzErrors.RpcError
e = EzErrors.PermissionError if rsp.findtext('error-message') == \
'permission denied' \
else EzErrors.RpcError
raise e(cmd=rpc_cmd_e, rsp=rsp, errs=err)
# Something unexpected happened - raise it up
except Exception as err:
warnings.warn("An unknown exception occured - please report.", RuntimeWarning)
warnings.warn("An unknown exception occured - please report.",
RuntimeWarning)
raise

# From 14.2 onward, junos supports JSON, so now code can be written as
Expand All @@ -877,8 +890,9 @@ def execute(self, rpc_cmd, **kvargs):
return json.loads(rpc_rsp_e.text)
except ValueError as ex:
# when data is {}{.*} types
if ex.message.startswith('Extra data'):
return json.loads(re.sub('\s?{\s?}\s?','',rpc_rsp_e.text))
if str(ex).startswith('Extra data'):
return json.loads(
re.sub('\s?{\s?}\s?', '', rpc_rsp_e.text))
else:
warnings.warn("Native JSON support is only from 14.2 onwards",
RuntimeWarning)
Expand Down Expand Up @@ -916,7 +930,6 @@ def execute(self, rpc_cmd, **kvargs):
else:
return ret_rpc_rsp


# -----------------------------------------------------------------------
# Context Manager
# -----------------------------------------------------------------------
Expand Down
25 changes: 14 additions & 11 deletions lib/jnpr/junos/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ def commit(self, **kvargs):
the candidate configuration on one control plane be
copied to the other control plane, checked for
correct syntax, and committed on both Routing Engines.
:param bool force_sync: On dual control plane systems, forces the candidate
configuration on one control plane to be copied to the
other control plane.
:param bool full: When true requires all the daemons to check and evaluate
the new configuration.
:param bool force_sync: On dual control plane systems, forces the
candidate configuration on one control plane to
be copied to the other control plane.
:param bool full: When true requires all the daemons to check and
evaluate the new configuration.
:param bool detail: When true return commit detail as XML
Expand Down Expand Up @@ -217,7 +217,7 @@ def pdiff(self, rb_id=0):
def load(self, *vargs, **kvargs):
"""
Loads changes into the candidate configuration. Changes can be
in the form of strings (text,set,xml), XML objects, and files.
in the form of strings (text,set,xml, json), XML objects, and files.
Files can be either static snippets of configuration or Jinja2
templates. When using Jinja2 Templates, this method will render
variables into the templates and then load the resulting change;
Expand All @@ -239,7 +239,7 @@ def load(self, *vargs, **kvargs):
* "conf","text","txt" is curly-text-style
* "set" - ascii-text, set-style
* "xml" - ascii-text, XML
* "set" - ascii-text, json
* "json" - ascii-text, json
.. note:: The format can specifically set using **format**.
Expand Down Expand Up @@ -293,7 +293,7 @@ def load(self, *vargs, **kvargs):
# note: this cannot be used if format='set', per Junos API.

overwrite = kvargs.get('overwrite', False)
if True == overwrite:
if overwrite is True:
rpc_xattrs['action'] = 'override'
elif kvargs.get('merge') is True:
del rpc_xattrs['action']
Expand All @@ -319,7 +319,7 @@ def _lset_format(kvargs, rpc_xattrs):
""" setup the kvargs/rpc_xattrs """
# when format is given, setup the xml attrs appropriately
if kvargs['format'] == 'set':
if True == overwrite:
if overwrite is True:
raise ValueError(
"conflicting args, cannot use 'set' with 'overwrite'")
rpc_xattrs['action'] = 'set'
Expand All @@ -339,8 +339,11 @@ def _lset_from_rexp(rpc):
kvargs['format'] = 'xml'
elif re.search(r'^\s*(set|delete|replace|rename)\s', rpc):
kvargs['format'] = 'set'
elif re.search(r'^[a-z:]*\s*[\w-]+\s+\{', rpc, re.I) and re.search(r'.*}\s*$', rpc):
elif re.search(r'^[a-z:]*\s*[\w-]+\s+\{', rpc, re.I) and \
re.search(r'.*}\s*$', rpc):
kvargs['format'] = 'text'
elif re.search(r'^\s*\{', rpc) and re.search(r'.*}\s*$', rpc):
kvargs['format'] = 'json'

def try_load(rpc_contents, rpc_xattrs):
try:
Expand Down Expand Up @@ -380,7 +383,7 @@ def try_load(rpc_contents, rpc_xattrs):
"You must define the format of the contents explicitly "
"to the function. Ex: format='set'")
if kvargs['format'] == 'xml':
# covert the XML string into XML structure
# covert the XML string into XML structure
rpc_contents = etree.XML(rpc_contents)
return try_load(rpc_contents, rpc_xattrs)
# ~! UNREACHABLE !~#
Expand Down

0 comments on commit d4416d2

Please sign in to comment.