Skip to content

Commit ac41408

Browse files
authored
Merge pull request #18 from APLA-Toolbox/improve-ci
Separate build and test
2 parents ad50fa5 + 481ae8f commit ac41408

10 files changed

Lines changed: 141 additions & 33 deletions

File tree

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
name: Python application
1+
name: Build
22

33
on: [push]
44

55
jobs:
66
build:
7-
87
runs-on: ubuntu-latest
98

109
steps:
@@ -33,11 +32,4 @@ jobs:
3332
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
3433
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
3534
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
36-
- name: Test with pytest
37-
run: |
38-
pip install pytest
39-
pytest
40-
- name: Upload coverage to Codecov
41-
uses: codecov/codecov-action@v1
42-
with:
43-
name: codecov-umbrella
35+

.github/workflows/tests.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Run tests
2+
3+
on: [push]
4+
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
9+
steps:
10+
- uses: actions/checkout@v1
11+
- name: Set up Python 3.7
12+
uses: actions/setup-python@v1
13+
with:
14+
python-version: 3.7
15+
- uses: actions/checkout@v1.0.0
16+
- uses: julia-actions/setup-julia@v1
17+
with:
18+
version: '1.4.1'
19+
- name: Install Julia dependencies
20+
run: |
21+
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/APLA-Toolbox/PDDL.jl"))'
22+
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/JuliaPy/PyCall.jl"))'
23+
- name: Install Python dependencies
24+
run: |
25+
python -m pip install --upgrade pip
26+
python -m pip install julia
27+
python -m pip install pycall
28+
- name: Lint with flake8
29+
run: |
30+
python -m pip install flake8
31+
# stop the build if there are Python syntax errors or undefined names
32+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
33+
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
34+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
35+
36+
test:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/checkout@v1
40+
- name: Set up Python 3.7
41+
uses: actions/setup-python@v1
42+
with:
43+
python-version: 3.7
44+
- uses: actions/checkout@v1.0.0
45+
- uses: julia-actions/setup-julia@v1
46+
with:
47+
version: '1.4.1'
48+
- name: Install Julia dependencies
49+
run: |
50+
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/APLA-Toolbox/PDDL.jl"))'
51+
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/JuliaPy/PyCall.jl"))'
52+
- name: Install Python dependencies
53+
run: |
54+
python -m pip install --upgrade pip
55+
python -m pip install julia
56+
python -m pip install pycall
57+
- name: Lint with flake8
58+
run: |
59+
python -m pip install flake8
60+
# stop the build if there are Python syntax errors or undefined names
61+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
62+
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
63+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
64+
- name: Test with pytest
65+
run: |
66+
pip install pytest
67+
pytest
68+
- name: Upload coverage to Codecov
69+
uses: codecov/codecov-action@v1
70+
with:
71+
name: codecov-umbrella

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
![tests](https://github.com/APLA-Toolbox/pyjulia-pddl/workflows/Run%20tests/badge.svg?branch=main&event=push)
2+
![build](https://github.com/APLA-Toolbox/pyjulia-pddl/workflows/Build/badge.svg?branch=main&event=push)
3+
4+
15
# Pyjulia PDDL
26

37
A Python wrapper using JuliaPy for the PDDL.jl package. It implements Planners (Best-First, Breadth-First, Depth-First) as class methods. Easy to use even in REFL mode. The AutomatedPlanner class is clear and understandable, easy to contribute to.

src/astar.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
class AStarBestFirstSearch():
1+
class AStarBestFirstSearch:
22
def __init__(self, automated_planner):
33
self.automated_planner = automated_planner
4-
4+
55
def search(self):
66
print("-/!\- No path found -/!\-")
77
return []

src/automated_planner.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from julia import PDDL
1717
from time import time as now
1818

19+
1920
class AutomatedPlanner:
2021
def __init__(self, domain_path, problem_path):
2122
self.pddl = PDDL
@@ -28,7 +29,7 @@ def __execute_action(self, action, state):
2829

2930
def transition(self, state, action):
3031
return self.pddl.transition(self.domain, state, action, check=False)
31-
32+
3233
def available_actions(self, state):
3334
return self.pddl.available(state, self.domain)
3435

@@ -66,7 +67,7 @@ def get_state_def_from_path(self, path):
6667
trimmed_path = []
6768
for node in path:
6869
trimmed_path.append(node.state)
69-
return trimmed_path
70+
return trimmed_path
7071

7172
def breadth_first_search(self, time_it=False):
7273
if time_it:

src/bfs.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
11
from .node import Node
22

3-
class BreadthFirstSearch():
3+
4+
class BreadthFirstSearch:
45
def __init__(self, automated_planner):
56
self.visited = []
67
self.automated_planner = automated_planner
78
self.init = Node(self.automated_planner.initial_state, automated_planner)
89
self.queue = [self.init]
9-
10+
1011
def search(self):
1112
while self.queue:
1213
current_node = self.queue.pop(0)
1314
if current_node not in self.visited:
1415
self.visited.append(current_node)
1516

16-
if self.automated_planner.satisfies(self.automated_planner.problem.goal, current_node.state):
17+
if self.automated_planner.satisfies(
18+
self.automated_planner.problem.goal, current_node.state
19+
):
1720
return current_node
18-
21+
1922
actions = self.automated_planner.available_actions(current_node.state)
2023
for act in actions:
21-
child = Node(state=self.automated_planner.transition(current_node.state, act), automated_planner=self.automated_planner, parent_action=act, parent=current_node)
24+
child = Node(
25+
state=self.automated_planner.transition(
26+
current_node.state, act
27+
),
28+
automated_planner=self.automated_planner,
29+
parent_action=act,
30+
parent=current_node,
31+
)
2232
if child in self.visited:
2333
continue
2434
self.queue.append(child)

src/dfs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
class DepthFirstSearch():
1+
class DepthFirstSearch:
22
def __init__(self, automated_planner):
33
self.automated_planner = automated_planner
4-
4+
55
def search(self):
66
print("-/!\- No path found -/!\-")
77
return []

src/dijkstra.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22
import math
33
from .heuristics import zero_heuristic
44

5-
class DijkstraBestFirstSearch():
5+
6+
class DijkstraBestFirstSearch:
67
def __init__(self, automated_planner):
78
self.automated_planner = automated_planner
8-
self.init = Node(self.automated_planner.initial_state, automated_planner, is_closed=False, is_open=True)
9+
self.init = Node(
10+
self.automated_planner.initial_state,
11+
automated_planner,
12+
is_closed=False,
13+
is_open=True,
14+
)
915
self.open_nodes_n = 1
1016
self.nodes = dict()
1117
self.nodes[self.__hash(self.init)] = self.init
@@ -17,19 +23,32 @@ def __hash(self, node):
1723

1824
def search(self):
1925
while self.open_nodes_n > 0:
20-
current_key = min([n for n in self.nodes if self.nodes[n].is_open], key=(lambda k: self.nodes[k].f_cost))
26+
current_key = min(
27+
[n for n in self.nodes if self.nodes[n].is_open],
28+
key=(lambda k: self.nodes[k].f_cost),
29+
)
2130
current_node = self.nodes[current_key]
2231

23-
if self.automated_planner.satisfies(self.automated_planner.problem.goal, current_node.state):
24-
return current_node
32+
if self.automated_planner.satisfies(
33+
self.automated_planner.problem.goal, current_node.state
34+
):
35+
return current_node
2536

2637
current_node.is_closed = True
2738
current_node.is_open = False
2839
self.open_nodes_n -= 1
29-
40+
3041
actions = self.automated_planner.available_actions(current_node.state)
3142
for act in actions:
32-
child = Node(state=self.automated_planner.transition(current_node.state, act), automated_planner=self.automated_planner, parent_action=act, parent=current_node, heuristic=zero_heuristic, is_closed=False, is_open=True)
43+
child = Node(
44+
state=self.automated_planner.transition(current_node.state, act),
45+
automated_planner=self.automated_planner,
46+
parent_action=act,
47+
parent=current_node,
48+
heuristic=zero_heuristic,
49+
is_closed=False,
50+
is_open=True,
51+
)
3352
child_hash = self.__hash(child)
3453
if child_hash in self.nodes:
3554
if self.nodes[child_hash].is_closed:

src/node.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
1-
class Node():
2-
def __init__(self, state, automated_planner, is_closed=None, is_open=None, parent_action=None, parent=None, g_cost=0, heuristic=None):
1+
class Node:
2+
def __init__(
3+
self,
4+
state,
5+
automated_planner,
6+
is_closed=None,
7+
is_open=None,
8+
parent_action=None,
9+
parent=None,
10+
g_cost=0,
11+
heuristic=None,
12+
):
313
self.state = state
414
self.parent_action = parent_action
515
self.parent = parent
@@ -19,7 +29,6 @@ def __init__(self, state, automated_planner, is_closed=None, is_open=None, paren
1929
self.h_cost = 0
2030
self.f_cost = self.g_cost + self.h_cost
2131

22-
2332
self.is_closed = is_closed
2433
self.is_open = is_open
2534

tests/test_automated_planner.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@ def test_available_actions():
1818

1919
apla = AutomatedPlanner("data/domain.pddl", "data/problem.pddl")
2020
actions = apla.available_actions(apla.initial_state)
21-
assert(len(actions) > 0)
21+
assert len(actions) > 0
22+
2223

2324
def test_execute_action():
2425
from src.automated_planner import AutomatedPlanner
2526

2627
apla = AutomatedPlanner("data/domain.pddl", "data/problem.pddl")
2728
actions = apla.available_actions(apla.initial_state)
2829
new_state = apla.transition(apla.initial_state, actions[0])
29-
assert(str(new_state) != str(apla.initial_state))
30+
assert str(new_state) != str(apla.initial_state)
31+
3032

3133
def test_state_assertion():
3234
from src.automated_planner import AutomatedPlanner

0 commit comments

Comments
 (0)