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
2 changes: 1 addition & 1 deletion .github/workflows/bandit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Bandit Scan
uses: shundor/python-bandit-scan@9cc5aa4a006482b8a7f91134412df6772dbda22c
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/black.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: psf/black@stable
with:
options: "--check --verbose"
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
uses: github/codeql-action/autobuild@v4

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
6 changes: 3 additions & 3 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.12"]
python-version: ["3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pylint_scores.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
python-version: ["3.13"]
steps:
- uses: Silleellie/pylint-github-action@v2
with:
Expand Down
35 changes: 17 additions & 18 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,34 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
python-version: ["3.13"]
env:
CC_TEST_REPORTER_ID: 0ab46c7acdcb9951ded95c2cb362eeec513807aa51c459b035509daf84e8f81e

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

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

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

- name: Test with pytest
run: |
pytest --cov loglan_core
bash <(curl -s https://codecov.io/bash)
ocular --data-file ".coverage" --config-file ".coveragerc"
- name: Install CodeClimate Test-Reporter
run: |
# download test reporter as a static binary
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
chmod +x ./cc-test-reporter
- name: Run coverage report
run: |
./cc-test-reporter before-build
./cc-test-reporter format-coverage -t coverage.py
./cc-test-reporter upload-coverage
- name: Finish build
pytest --cov=loglan_core --cov-report=xml --cov-report=term

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
fail_ci_if_error: false

- name: Upload coverage to Ocular
run: |
./cc-test-reporter after-build --exit-code $?
ocular --data-file ".coverage" --config-file ".coveragerc"
continue-on-error: true
6 changes: 3 additions & 3 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ jobs:
VERSION=$(echo "${{ steps.get_version.outputs.version }}")
echo $VERSION

- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.10"
python-version: "3.13"
- name: Update version and download URL in pyproject.toml
run: |
VERSION="${{ steps.get_version.outputs.version }}"
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

![Codecov](https://img.shields.io/codecov/c/github/torrua/loglan_core?logo=Codecov&logoColor=%23F01F7A&label=codecov)
![Scrutinizer code quality (GitHub/Bitbucket)](https://img.shields.io/scrutinizer/quality/g/torrua/loglan_core/main?logo=Scrutinizer%20CI&logoColor=%238A9296&label=Scrutinizer%20CC&link=https%3A%2F%2Fscrutinizer-ci.com%2Fg%2Ftorrua%2Floglan_core%2F%3Fbranch%3Dmain)
![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability-percentage/torrua/loglan_core?logo=Code%20Climate)
![pylint](https://img.shields.io/badge/PyLint-10.00-brightgreen?logo=python&logoColor=white)
[![Pytest](https://github.com/torrua/loglan_core/actions/workflows/pytest.yml/badge.svg)](https://github.com/torrua/loglan_core/actions/workflows/pytest.yml)
![Bandit Status](https://img.shields.io/github/actions/workflow/status/torrua/loglan_core/bandit.yml?label=bandit)
Expand Down
53 changes: 53 additions & 0 deletions loglan_core/addons/word_sourcer.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,56 @@ def words_from_source_cpd(cls, sources: list[str]) -> Select[tuple[BaseWord]]:
.filter(BaseWord.name.in_(sources))
.filter(BaseWord.type_id.in_(type_ids))
)

@staticmethod
def prepare_origin(origin: str) -> str:
"""
Remove text in parentheses, reverse characters between slash, remove slash.

Examples:
zav(lo)+da(n)z(a)+fo/l(ma) => zav+daz+flo
be(rt)i+n+(t)rac(i)+ve(sl)o => bei+n+rac+veo

Args:
origin: str

Returns: str
"""
origin_list = list(re.sub(r"\([^)]*\)", "", origin))
for index, char in enumerate(origin_list):
if char == "/" and 0 < index < len(origin_list) - 1:
start_index = index - 1
end_index = index + 2

origin_list[start_index:end_index] = reversed(
origin_list[start_index:end_index]
)
return "".join(origin_list).replace("/", "")

@staticmethod
def get_parent_complex(origin: str) -> str:
"""

Args:
Example:
zavdazflo -> zav(lo)+da(n)z(a)+fo/l(ma) => dazflo
zanynurkokmio -> za(v)n(o)+y+nur+kok(fa)+mi(tr)o => nurkokmio
cabsrusia -> cab(ro)+su/r(na)+si(tf)a => srusia
beinracveo -> be(rt)i+n+(t)rac(i)+ve(sl)o => racveo
Returns:
"""
origin_list = WordSourcer.prepare_origin(origin).split("+")
origin_list = origin_list[1:]
origin_list = (
origin_list if origin_list[0] not in ["y", "r", "n"] else origin_list[1:]
)
return "".join(origin_list)


class OriginParser: # pylint: disable=too-few-public-methods
"""
Test Class
"""

def __init__(self, word: BaseWord):
self.word = word
64 changes: 60 additions & 4 deletions tests/test_sync/test_loglan_core/test_addons/test_word_sourcer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Base Model unit tests."""

import pytest

from loglan_core import Word
Expand All @@ -15,6 +16,7 @@ class TestWordSources:

# words_objects = [Word(**obj) for obj in other_words]
types = []

def test_get_sources_afx(self, db_session):

afx = Word.get_by_id(db_session, 3)
Expand All @@ -35,7 +37,7 @@ def test_get_sources_prim_d(self, db_session):

prim_d = WordSelector().by_name(name="humnu").scalar(db_session)
result = self.aws.get_sources_prim(prim_d)
assert result == 'humnu: humni'
assert result == "humnu: humni"

def test_not_get_sources_c_prim(self, db_session):
db_session.add_all([Word(**w) for w in other_words])
Expand All @@ -49,10 +51,10 @@ def test_get_sources_cpx(self, db_session):
cpx = WordSelector().by_name("prukao").scalar(db_session)
result = db_session.execute(self.aws.get_sources_cpx(cpx)).scalars().all()
assert len(result) == 2
assert result[0].name in ["kakto", "pruci" ]
assert result[0].name in ["kakto", "pruci"]

result = self.aws.get_sources_cpx(cpx, as_str=True)
assert sorted(result) == sorted(['pruci', 'kakto'])
assert sorted(result) == sorted(["pruci", "kakto"])

not_cpx = WordSelector().by_name("pru").scalar(db_session)
result = self.aws.get_sources_cpx(not_cpx)
Expand All @@ -68,7 +70,7 @@ def test_get_sources_cpd(self, db_session):

result = self.aws.get_sources_cpd(cpd, as_str=True)
assert len(result) == 2
assert result == ['ai', 'ai']
assert result == ["ai", "ai"]

prim = WordSelector().by_name("kakto").scalar(db_session)
result = self.aws.get_sources_cpd(prim, as_str=True)
Expand All @@ -83,3 +85,57 @@ def test_prepare_sources_cpd(self, db_session):
prim = WordSelector().by_name("cii").scalar(db_session)
assert self.aws._prepare_sources_cpd(prim) == []


class TestWordSourcerPrepareOrigin:
"""Unit tests for WordSourcer.prepare_origin method using pytest"""

def test_basic_example_1(self):
"""Test basic functionality with first example from docstring"""
# Input: zav(lo)+da(n)z(a)+fo/l(ma)
# After parenth removal: zav+da+z+fo/l
# After slash processing: za
result = WordSourcer.prepare_origin("zav(lo)+da(n)z(a)+fo/l(ma)")
assert result == "zav+daz+flo"

def test_basic_example_2(self):
"""Test basic functionality with second example from docstring"""
# Input: be(rt)i+n+(t)rac(i)+ve(sl)o
# After parenth removal: bei+n+rac+i+ve/lo
# After slash processing: bei+n+rac+i+velo
result = WordSourcer.prepare_origin("be(rt)i+n+(t)rac(i)+ve(sl)o")
assert result == "bei+n+rac+veo"

def test_empty_string(self):
"""Test handling of empty string"""
result = WordSourcer.prepare_origin("")
assert result == ""

def test_no_parentheses(self):
"""Test string with no parentheses"""
result = WordSourcer.prepare_origin("abc/def")
assert result == "abdcef"

def test_no_slashes(self):
"""Test string with no slashes"""
result = WordSourcer.prepare_origin("abc(def)+ghi(jkl)")
assert result == "abc+ghi"

def test_multiple_slashes(self):
"""Test string with multiple slashes"""
result = WordSourcer.prepare_origin("a/b/c+d/e/f")
assert result == "bca+efd"

def test_slash_at_boundary(self):
"""Test string with slash at beginning or end"""
result = WordSourcer.prepare_origin("/abc+def/")
assert result == "abc+def"

def test_complex_case(self):
"""Test complex case with multiple parentheses and slashes"""
result = WordSourcer.prepare_origin("a(b)c/d(e)f+g(h)i/j(k)l")
assert result == "adcf+gjil"

def test_adjacent_operations(self):
"""Test parentheses adjacent to slashes"""
result = WordSourcer.prepare_origin("a(b)/c(d)+e(f)/g(h)")
assert result == "ca+ge"