Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 1.0.4 #305

Merged
merged 39 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
56ac9f0
Merge pull request #284 from arista-eosplus/master
chieto-arista Aug 16, 2023
10b2714
Update VERSION
chieto-arista Aug 16, 2023
6ada0c5
some physical duts supports only up to 8 min-link values, adopting th…
Sep 13, 2023
9d2c1b4
Merge pull request #285 from dlyssenko/fix_min-links
dlyssenko Sep 13, 2023
954f48a
add apiVersion parameter
nitzan-tz Oct 18, 2023
c6c5959
Merge pull request #1 from nitzan-tz/nitzan-tz-patch-1
nitzan-tz Oct 18, 2023
c9d2687
Merge pull request #289 from nitzan-tz/develop
dlyssenko Dec 1, 2023
7070b2d
fix for issue #286
Dec 4, 2023
fd0c185
removed old commented code and made some text adjustments to make pep…
Dec 4, 2023
025a40f
reverting to legacy interface exposure - to prevent failures with new…
Dec 5, 2023
2386f88
added a false positive case to UT fixture for banner section
Dec 5, 2023
92ea00d
a very minor optimization for the updated code
Dec 5, 2023
afa6ded
reverting last change, due to incompatibility with py3.7
Dec 6, 2023
2246f66
Merge pull request #291 from dlyssenko/fix_chunkification
dlyssenko Dec 6, 2023
59c1cda
cleanup old "mock" leftovers
a-detiste Feb 28, 2024
1f2d8e1
Migrate to importlib
fabaff Apr 3, 2024
c508b63
forced modules generation for html format
Aug 2, 2024
5445a39
Merge pull request #297 from dlyssenko/attempt_to_fix_missing_modules
dlyssenko Aug 2, 2024
7429cb1
forced modules generation for html format
Aug 2, 2024
aa5dc19
Merge pull request #298 from dlyssenko/attempt_to_fix_missing_modules
dlyssenko Aug 2, 2024
7dc4546
forced modules generation for html format
Aug 2, 2024
996f707
Merge pull request #299 from dlyssenko/attempt_to_fix_missing_modules2
dlyssenko Aug 2, 2024
54b3cf2
forced modules generation for html format
Aug 2, 2024
6b9d3a6
Merge pull request #300 from dlyssenko/attempt_to_fix_missing_modules3
dlyssenko Aug 2, 2024
b616317
Update ci.yml
dlyssenko Aug 3, 2024
3b174e4
Merge pull request #301 from arista-eosplus/dlyssenko-patch-1
dlyssenko Aug 3, 2024
ca94e9b
Merge pull request #295 from fabaff/patch-1
dlyssenko Aug 3, 2024
39041bc
Merge pull request #293 from a-detiste/develop
dlyssenko Aug 3, 2024
b4c5523
fixing system test issue where non-existent interface could be selected
Aug 14, 2024
a2d0508
Merge pull request #302 from dlyssenko/fix_eos_ptest
dlyssenko Aug 14, 2024
4c9381a
fixing system test issue where mlag test fails on Ethernet1
Aug 14, 2024
519be98
Merge pull request #303 from dlyssenko/fix_eos_mlag_ptest
dlyssenko Aug 15, 2024
7f16691
updated number for invalid link
dlyssenko Aug 16, 2024
0669b66
Merge pull request #304 from dlyssenko/dlyssenko-update-invalid-min-l…
dlyssenko Aug 16, 2024
6dfe6be
Create release-notes-1.0.r.rst
dlyssenko Aug 19, 2024
b7ffe06
Update VERSION
dlyssenko Aug 19, 2024
dff476c
Update __init__.py
dlyssenko Aug 19, 2024
2a93891
Create release-notes-1.0.4.rst
dlyssenko Aug 20, 2024
4e75a7c
Delete docs/release-notes-1.0.r.rst
dlyssenko Aug 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: CI
on: [ pull_request, workflow_dispatch ]
on: [ pull_request, workflow_dispatch, pull_request_target ]
jobs:
build:
runs-on: ubuntu-latest
Expand Down
6 changes: 5 additions & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ build:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"
jobs:
pre_build:
- make -C docs modules


# Build documentation in the "docs/" directory with Sphinx
sphinx:
Expand All @@ -33,4 +37,4 @@ python:
install:
- requirements: dev-requirements.txt
- method: pip
path: .
path: .
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.3
1.0.4
1 change: 0 additions & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
-r requirements.txt
mock
coveralls
twine
check-manifest
Expand Down
2 changes: 1 addition & 1 deletion docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ html:
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."

modules:
python $(CWD)/generate_modules.py
python3 $(CWD)/generate_modules.py

docs: clean modules html

Expand Down
22 changes: 22 additions & 0 deletions docs/release-notes-1.0.4.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Release 1.0.4
-------------

2024-08-19
\- the major reason for this release is to fix documentation issue on `readthedocs <https://pyeapi.readthedocs.io/en/latest/>`_ site

New Modules
^^^^^^^^^^^

Enhancements
^^^^^^^^^^^^

Fixed
^^^^^
* System test fixes ( `#285 <https://github.com/arista-eosplus/pyeapi/pull/285>`_, `#291 <https://github.com/arista-eosplus/pyeapi/pull/291>`_,
`#302 <https://github.com/arista-eosplus/pyeapi/pull/302>`_, `#303 <https://github.com/arista-eosplus/pyeapi/pull/303>`_ )
* Fixed PR `#289 <https://github.com/arista-eosplus/pyeapi/pull/289>`_: allow specifying API version in requests.
* Fixed PR `#286 <https://github.com/arista-eosplus/pyeapi/pull/291>`_: a regression introduced by PR #220, where parsing a non-empty banner section may fail
* Fixed *modules* section on `readthedocs <https://pyeapi.readthedocs.io/en/develop/modules.html>`_ site (PR `#300 <https://github.com/arista-eosplus/pyeapi/pull/300>`_)

Known Caveats
^^^^^^^^^^^^^
2 changes: 1 addition & 1 deletion pyeapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
__version__ = '1.0.3'
__version__ = '1.0.4'
__author__ = 'Arista EOS+'


Expand Down
46 changes: 29 additions & 17 deletions pyeapi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,27 +718,39 @@ def _chunkify( self, config, indent=0 ):
last parsed (sub)section, which in turn may contain sub-sections
"""
def is_subsection_present( section, indent ):
return any( [line[ indent ] == ' ' for line in section] )
return any( line[ indent ] == ' ' for line in section )

def get_indent( line ):
return len( line ) - len( line.lstrip() )

sections = {}
key = None
banner = None
for line in config.splitlines( keepends=True )[ indent > 0: ]:
# indent > 0: no need processing subsection line, which is 1st line
if line[ indent ] == ' ': # section continuation
sections[key] += line
line_rs = line.rstrip()
if indent == 0:
if banner:
sections[ banner ] += line
if line_rs == 'EOF':
banner = None
continue
if line.startswith( 'banner ' ):
banner = line_rs
sections[ banner ] = line
continue
if get_indent( line_rs ) > indent: # i.e. subsection line
# key is always expected to be set by now
sections[ key ] += line
continue
# new section is found (if key is not None)
if key: # process prior (last recorded) section
lines = sections[key].splitlines()[ 1: ]
if len( lines ): # section may contain sub-sections
ind = len( lines[0] ) - len( lines[0].lstrip() )
if is_subsection_present( lines, ind ):
subs = self._chunkify( sections[key], indent=ind )
subs.update( sections )
sections = subs
elif indent > 0: # record only subsections
del sections[key]
key = line.rstrip()
sections[key] = line
subsection = sections.get( key, '' ).splitlines()[ 1: ]
if subsection:
sub_indent = get_indent( subsection[0] )
if is_subsection_present( subsection, sub_indent ):
parsed = self._chunkify( sections[key], indent=sub_indent )
parsed.update( sections )
sections = parsed
key = line_rs
sections[ key ] = line
return sections

def section(self, regex, config='running_config'):
Expand Down
2 changes: 2 additions & 0 deletions pyeapi/eapilib.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ def request(self, commands, encoding=None, reqid=None, **kwargs):
reqid = id(self) if reqid is None else reqid
params = {'version': 1, 'cmds': commands, 'format': encoding}
streaming = False
if 'apiVersion' in kwargs:
params['version'] = kwargs['apiVersion']
if 'autoComplete' in kwargs:
params['autoComplete'] = kwargs['autoComplete']
if 'expandAliases' in kwargs:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
# $ pip install -e .[dev,test]
extras_require={
'dev': ['check-manifest', 'pep8', 'pyflakes', 'twine'],
'test': ['coverage', 'mock'],
'test': ['coverage'],
},
)

Expand Down
26 changes: 16 additions & 10 deletions test/fixtures/running_config.text
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,22 @@ vlan 300
state active
no private-vlan
!
banner login
+++++++++++++++++++++++++++++++++++++++++
banner:

vlan 1
this
is the loging ban
that would b emult
EOF
!

banner motd
this text
can be multine
EOF
!
interface Port-Channel10
no description
no shutdown
Expand Down Expand Up @@ -2106,16 +2122,6 @@ no ip tacacs source-interface
!
no vxlan vni notation dotted
!
banner login
this
is the loging ban
that would b emult
EOF
banner motd
this text
can be multine
EOF
!
system coredump compressed
!
no dot1x system-auth-control
Expand Down
22 changes: 18 additions & 4 deletions test/lib/systestlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import random

from testlib import get_fixture
from pyeapi.utils import CliVariants

import pyeapi.client

Expand All @@ -48,19 +49,32 @@ def setUp(self):

self.duts = list()
for name in config.sections():
if name.startswith('connection:') and 'localhost' not in name:
name = name.split(':')[1]
self.duts.append(pyeapi.client.connect_to(name))
if not name.startswith('connection:'):
continue
if 'localhost' in name:
continue
name = name.split(':')[1]
self.duts.append( pyeapi.client.connect_to(name) )
# revert to a legacy behavior for interface availability
if self.duts[ -1 ]:
self.duts[ -1 ].config( CliVariants(
'service interface inactive expose', 'enable') )

def sort_dict_by_keys(self, d):
keys = sorted(d.keys())
return dict([(k, d[k]) for k in keys])


def random_interface(dut, exclude=None):
# interfaces read in 'show run all' and those actually present may differ,
# thus interface list must be picked from the actually present
if not getattr( random_interface, 'present', False ):
random_interface.present = dut.run_commands(
'show interfaces', send_enable=False )[ 0 ][ 'interfaces' ].keys()
exclude = [] if exclude is None else exclude
interfaces = dut.api('interfaces')
names = [name for name in list(interfaces.keys()) if name.startswith('Et')]
names = [ name for name in list(interfaces.keys()) if name.startswith('Et') ]
names = [ name for name in names if name in random_interface.present ]

exclude_interfaces = dut.settings.get('exclude_interfaces', [])
if exclude_interfaces:
Expand Down
6 changes: 3 additions & 3 deletions test/system/test_api_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class TestResourceInterfaces(DutSystemTest):

def test_get(self):
for dut in self.duts:
intf = random_interface(dut)
intf = random_interface( dut, exclude=['Ethernet1'] )
dut.config(['default interface %s' % intf,
'interface %s' % intf,
'description this is a test',
Expand Down Expand Up @@ -390,7 +390,7 @@ def test_get_lacp_mode_with_default(self):

def test_minimum_links_valid(self):
for dut in self.duts:
minlinks = random_int(1, 16)
minlinks = random_int(1, 8) # some physical duts may have only 8 links
dut.config(['no interface Port-Channel1',
'interface Port-Channel1'])
result = dut.api('interfaces').set_minimum_links('Port-Channel1',
Expand All @@ -403,7 +403,7 @@ def test_minimum_links_valid(self):

def test_minimum_links_invalid_value(self):
for dut in self.duts:
minlinks = random_int(129, 256) # some duts may support up to 128
minlinks = 1025 # hope it will hold for a while
result = dut.api(
'interfaces').set_minimum_links('Port-Channel1', minlinks)
self.assertFalse(result)
Expand Down
4 changes: 2 additions & 2 deletions test/unit/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import sys
import os
import unittest
import imp
import importlib

sys.path.append(os.path.join(os.path.dirname(__file__), '../lib'))

Expand Down Expand Up @@ -227,7 +227,7 @@ class TestClient(unittest.TestCase):
def setUp(self):
if 'EAPI_CONF' in os.environ:
del os.environ['EAPI_CONF']
imp.reload(pyeapi.client)
importlib.reload(pyeapi.client)

def test_load_config_for_connection_with_filename(self):
conf = get_fixture('eapi.conf')
Expand Down
Loading