Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 6 additions & 7 deletions .github/workflows/generate-changelog.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
name: Changelog CI

on:
pull_request:
types: [ opened ]
#on:
# pull_request:
# types: [ opened ]
# Not working for now...

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Run Changelog CI
uses: saadmk11/changelog-ci@v1.1.2
uses: saadmk11/changelog-ci@v1.2.0
with:
config_file: changelog-ci-config.yaml
config_file: changelog-ci-config.yaml
140 changes: 72 additions & 68 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# This workflow runs the test suites with different versions of python
name: tests

on: [push, pull_request]
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
tests:
Expand All @@ -14,74 +18,74 @@ jobs:
# pub400 closes the connection if there are too many requests coming from the same IP address
max-parallel: 1
matrix:
python-version: ["3.8", "3.12", "3.13"]
python-version: ["3.12"]
os: [ubuntu-latest, windows-latest]
fail-fast: false

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies linux
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get install -y xvfb x3270 locales xterm
sudo locale-gen en_US

- name: Install dependencies windows
if: matrix.os == 'windows-latest'
run: |
choco install wc3270
echo "C:\Program Files\wc3270" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Install python dependencies
run: |
python -m pip install -r requirements-dev.txt

- name: Lint
run: |
inv lint

- name: Run utests with coverage
run: |
coverage run --branch --source Mainframe3270/ -m pytest --verbose utest/
coverage report
coverage xml

- name: Upload unit test coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: coverage.xml
flags: unit
move_coverage_to_trash: true

- name: Run atests with coverage linux
if: matrix.os == 'ubuntu-latest'
run: |
LANG=en_US.iso88591 xvfb-run coverage run --branch --source Mainframe3270/ -m robot $ROBOT_OPTIONS atest/
coverage report
coverage xml

- name: Run atests with coverage windows
if: matrix.os == 'windows-latest'
run: |
coverage run --branch --source Mainframe3270/ -m robot $ROBOT_OPTIONS atest/
coverage report
coverage xml

- name: Upload acceptance tests coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: coverage.xml
flags: acceptance

- uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: Tests results python${{ matrix.python-version }} - ${{ matrix.os }}
path: logs/
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies linux
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get install -y xvfb x3270 locales xterm
sudo locale-gen en_US

- name: Install dependencies windows
if: matrix.os == 'windows-latest'
run: |
choco install wc3270
echo "C:\Program Files\wc3270" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Install python dependencies
run: |
python -m pip install -r requirements-dev.txt

- name: Lint
run: |
inv lint

- name: Run utests with coverage
run: |
coverage run --branch --source Mainframe3270/ -m pytest --verbose utest/
coverage report
coverage xml

- name: Upload unit test coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: coverage.xml
flags: unit
move_coverage_to_trash: true

- name: Run atests with coverage linux
if: matrix.os == 'ubuntu-latest'
run: |
LANG=en_US.iso88591 xvfb-run coverage run --branch --source Mainframe3270/ -m robot $ROBOT_OPTIONS atest/
coverage report
coverage xml

- name: Run atests with coverage windows
if: matrix.os == 'windows-latest'
run: |
coverage run --branch --source Mainframe3270/ -m robot $ROBOT_OPTIONS atest/
coverage report
coverage xml

- name: Upload acceptance tests coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: coverage.xml
flags: acceptance

- uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: Tests results python${{ matrix.python-version }} - ${{ matrix.os }}
path: logs/
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ log.html
output.xml
report.html
screenshot*.html
screenshot*.png
atest/**/session.*3270
atest/log.html
atest/output.xml
Expand All @@ -36,3 +37,7 @@ htmlcov

# Personal test cases
atest/test_with_login.robot
utest/
.hypothesis/
.robotcode_cache/
*.isorted
15 changes: 6 additions & 9 deletions Mainframe3270/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import os
from datetime import timedelta
from typing import Any

from robot.api import logger
from robot.api.deco import keyword
from robot.libraries.BuiltIn import BuiltIn, RobotNotRunningError
from robot.utils import ConnectionCache
from robotlibcore import DynamicCore

from Mainframe3270.keywords import (
AssertionKeywords,
CommandKeywords,
Expand Down Expand Up @@ -150,17 +148,16 @@ def __init__(
self.timeout = convert_timeout(timeout)
self.wait_time = convert_timeout(wait_time)
self.wait_time_after_write = convert_timeout(wait_time_after_write)
self.img_folder = img_folder
self._running_on_failure_keyword = False
self.register_run_on_failure_keyword(run_on_failure_keyword)
self.model = model
self.cache = ConnectionCache()
# When generating the library documentation with libdoc, BuiltIn.get_variable_value throws
# a RobotNotRunningError. Therefore, we catch it here to be able to generate the documentation.
try:
self.output_folder = BuiltIn().get_variable_value("${OUTPUT DIR}")
self.img_folder = BuiltIn().get_variable_value("${OUTPUT_DIR}")
except RobotNotRunningError:
self.output_folder = os.getcwd()
self.img_folder = os.getcwd()
self._running_on_failure_keyword = False
self.register_run_on_failure_keyword(run_on_failure_keyword)
self.model = model
self.cache = ConnectionCache()
libraries = [
AssertionKeywords(self),
CommandKeywords(self),
Expand Down
2 changes: 0 additions & 2 deletions Mainframe3270/keywords/assertions.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import re
from typing import List, Optional

from robot.api import logger
from robot.api.deco import keyword
from robot.utils import Matcher

from Mainframe3270.librarycomponent import LibraryComponent


Expand Down
2 changes: 0 additions & 2 deletions Mainframe3270/keywords/commands.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import time
from typing import Optional, Union

from robot.api.deco import keyword

from Mainframe3270.librarycomponent import LibraryComponent
from Mainframe3270.utils import ResultMode, prepare_position_as

Expand Down
18 changes: 13 additions & 5 deletions Mainframe3270/keywords/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import shlex
from os import name as os_name
from typing import List, Optional, Union

from robot.api import logger
from robot.api.deco import keyword

from Mainframe3270.librarycomponent import LibraryComponent
from Mainframe3270.py3270 import Emulator

Expand All @@ -16,10 +14,11 @@ class ConnectionKeywords(LibraryComponent):
def open_connection(
self,
host: str,
LU: Optional[str] = None,
lu: Optional[str] = None,
port: int = 23,
extra_args: Optional[Union[List[str], os.PathLike]] = None,
alias: Optional[str] = None,
utf8: bool = True,
) -> int:
"""Create a connection to an IBM3270 mainframe with the default port 23.
To establish a connection, only the hostname is required.
Expand All @@ -41,6 +40,9 @@ def open_connection(
| -charset french
| -port 992

By default, the `utf8` argument is set to `True`, which will add the `-utf8` option to the `extra_args` list.
If you want to disable UTF-8 encoding, you can set the `utf8` argument to `False`.

Please ensure that the arguments provided are available for your specific x3270 application and version.
Refer to the [https://x3270.miraheze.org/wiki/Wc3270/Command-line_options|wc3270 command line options]
for a subset of available options.
Expand All @@ -53,20 +55,26 @@ def open_connection(
when switching between connections using the `Switch Connection` keyword. For more information on opening
and switching between multiple connections, please refer to the `Concurrent Connections` section.

Example:
Examples:
| Open Connection | Hostname |
| Open Connection | Hostname | LU=LUname |
| Open Connection | Hostname | port=992 |
| Open Connection | Hostname | utf8=${False} |
| @{extra_args} | Create List | -accepthostname | myhost.com | -cafile | ${CURDIR}/cafile.crt |
| Append To List | ${extra_args} | -port | 992 |
| Open Connection | Hostname | extra_args=${extra_args} |
| Open Connection | Hostname | extra_args=${CURDIR}/argfile.txt |
| Open Connection | Hostname | alias=my_first_connection |
"""
if utf8:
if extra_args is None:
extra_args = ["-utf8"]
elif isinstance(extra_args, list):
extra_args.append("-utf8")
extra_args = self._process_args(extra_args)
model = self._get_model_from_list_or_file(extra_args)
connection = Emulator(self.visible, self.timeout, extra_args, model or self.model)
host_string = f"{LU}@{host}" if LU else host
host_string = f"{lu}@{host}" if lu else host
if self._port_in_extra_args(extra_args):
if port != 23:
logger.warn(
Expand Down
16 changes: 7 additions & 9 deletions Mainframe3270/keywords/read_write.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import time
from typing import Any, Optional

from robot.api.deco import keyword
from robot.libraries.BuiltIn import BuiltIn

from Mainframe3270.librarycomponent import LibraryComponent
from Mainframe3270.utils import ResultMode, prepare_positions_as

Expand Down Expand Up @@ -124,12 +121,13 @@ def write(self, txt: str) -> None:

@keyword("Write Unicode")
def write_unicode(self, txt: str) -> None:
"""Send a string *and Enter* to the screen at the current cursor location.
"""Send a Unicode string using the execute command String("") *and Enter* to the screen at the current
cursor location.

Example:
| Write Unicode | something |
| Write Unicode | ß |
"""
self.mf.exec_command(f'String("{txt}")'.encode('utf-8'))
self.mf.exec_command(f'String("{txt}")'.encode("utf-8"))
time.sleep(self.wait_time_after_write)
self.mf.send_enter()

Expand All @@ -144,12 +142,12 @@ def write_bare(self, txt: str) -> None:

@keyword("Write Unicode Bare")
def write_unicode_bare(self, txt: str) -> None:
"""Send only the string to the screen at the current cursor location.
"""Send only the Unicode string using the execute command String("") to the screen at the current cursor location.

Example:
| Write Unicode Bare | something |
| Write Unicode Bare | Æ |
"""
self.mf.exec_command(f'String("{txt}")'.encode('utf-8'))
self.mf.exec_command(f'String("{txt}")'.encode("utf-8"))
time.sleep(self.wait_time_after_write)

@keyword("Write In Position")
Expand Down
Loading