Skip to content

Commit e1a61e5

Browse files
committed
openflow: add configure.py
A class to configure the OCI engine, containers and tool names.
1 parent 5a44906 commit e1a61e5

File tree

14 files changed

+368
-9
lines changed

14 files changed

+368
-9
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ jobs:
2727
pylint -s n openflow
2828
git diff --check --cached
2929
- name: Test
30-
run: pytest test
30+
run: |
31+
pytest test
32+
make -C examples/configure

Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#!/usr/bin/make
22

33
check:
4-
pycodestyle openflow
5-
pylint -s n openflow
4+
pycodestyle openflow examples
5+
pylint -s n openflow examples
66
git diff --check --cached
77
pytest test
8+
make -C examples/configure
89

910
clean:
1011
py3clean .

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,33 @@ Currently, it is based on `GHDL`, `Yosys`, `ghdl-yosys-plugin`, `nextpnr`,
1313

1414
> **NOTE:** it started as part of [PyFPGA](https://github.com/PyFPGA/pyfpga)
1515
> and will be used to solves the `openflow` **tool**.
16+
17+
## Installation
18+
19+
Openflow requires Python `>=3.6`. For now, it's only available as a git repository
20+
hosted on GitHub. It can be installed with pip:
21+
22+
```
23+
pip install 'git+https://github.com/PyFPGA/pyfpga#egg=pyfpga'
24+
```
25+
26+
> On GNU/Linux, installing pip packages on the system requires `sudo`.
27+
> Alternatively, use `--local` for installing PyFPGA in your HOME.
28+
29+
You can get a copy of the repository either through git clone or downloading a
30+
tarball/zipfile:
31+
32+
```
33+
git clone https://github.com/PyFPGA/openflow.git
34+
cd openflow
35+
```
36+
37+
Then, use pip from the root of the repo:
38+
39+
```
40+
pip install -e .
41+
```
42+
43+
> With `-e` (`--editable`) your application is installed into site-packages via
44+
> a kind of symlink. That allows pulling changes through git or changing the
45+
> branch, without the need to reinstall the package.

examples/configure/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
EXAMPLES=$(wildcard *.py)
2+
3+
.PHONY: $(EXAMPLES)
4+
5+
all: $(EXAMPLES)
6+
7+
$(EXAMPLES):
8+
python3 $@

examples/configure/defaults.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""Example about default values."""
2+
3+
from openflow.configure import ConfigureTools
4+
5+
cfg = ConfigureTools()
6+
7+
for tool in cfg.get_tools():
8+
print(cfg.get_command(tool))

examples/configure/file.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""Example about to specify a file."""
2+
3+
from openflow.configure import ConfigureTools
4+
5+
cfg = ConfigureTools('file.yml')
6+
7+
for tool in cfg.get_tools():
8+
print(cfg.get_command(tool))

examples/configure/file.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
engine:
2+
name: example
3+
volumes:
4+
- "path1:path2"
5+
- "path3:path4"
6+
work: .
7+
options: general-option
8+
tools:
9+
example1:
10+
name: alt-example1
11+
container: hdlc/example1
12+
example2:
13+
name: alt-example2
14+
container: hdlc/example2
15+
options: particular-option

examples/configure/methods.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""Example about to use the different methods."""
2+
3+
from openflow.configure import ConfigureTools
4+
5+
cfg = ConfigureTools()
6+
7+
print('* Defaults for GHDL:')
8+
print(cfg.get_command('ghdl'))
9+
10+
print('* Setting a different engine:')
11+
cfg.set_engine('podman')
12+
print(cfg.get_command('ghdl'))
13+
14+
print('* Setting different volumes:')
15+
cfg.set_volumes(['v1:v1', 'v2:v2'])
16+
print(cfg.get_command('ghdl'))
17+
18+
print('* Setting a different work:')
19+
cfg.set_work('/tmp')
20+
print(cfg.get_command('ghdl'))
21+
22+
print('* Setting different general options:')
23+
cfg.set_general_options('--general option')
24+
print(cfg.get_command('ghdl'))
25+
26+
print('* Setting a new container:')
27+
cfg.set_container('ghdl', 'alt-ghdl-container')
28+
print(cfg.get_command('ghdl'))
29+
30+
print('* Setting a new tool name:')
31+
cfg.set_name('ghdl', 'alt-ghdl-name')
32+
print(cfg.get_command('ghdl'))
33+
34+
print('* Setting particular options:')
35+
cfg.set_particular_options('ghdl', '--particular option')
36+
print(cfg.get_command('ghdl'))

openflow/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
__version__ = '0.1.0'
44

55
from openflow.openflow import Openflow
6+
from openflow.configure import ConfigureTools

openflow/configure.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#
2+
# Copyright (C) 2020-2021 Rodrigo A. Melo
3+
#
4+
# This program is free software: you can redistribute it and/or modify
5+
# it under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation, either version 3 of the License, or
7+
# (at your option) any later version.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
#
17+
18+
"""openflow.configure
19+
20+
A Class to configure the OCI engine, the containers and the name of the
21+
underlying FOSS tools.
22+
"""
23+
24+
25+
import os
26+
from yaml import safe_load, dump
27+
28+
29+
class ConfigureTools:
30+
"""Configure Tools."""
31+
32+
def __init__(self, filename='.openflow.yml'):
33+
"""Class constructor."""
34+
usrfile = os.path.join(os.path.expanduser('~'), filename)
35+
prjfile = os.path.join(os.path.dirname(__file__), 'configure.yml')
36+
if os.path.exists(filename):
37+
filepath = filename
38+
elif os.path.exists(usrfile):
39+
filepath = usrfile
40+
else:
41+
filepath = prjfile
42+
self.configs = {}
43+
with open(filepath, 'r') as file:
44+
self.configs = safe_load(file)
45+
46+
def get_command(self, tool):
47+
"""Get the command-line needed to run a tool."""
48+
engine = self.configs['engine']['name']
49+
name = self.configs['tools'][tool]['name']
50+
if engine is not None:
51+
oci = [
52+
engine,
53+
'run --rm',
54+
'-v ' + (' -v ').join(self.configs['engine']['volumes']),
55+
'-w ' + self.configs['engine']['work'],
56+
self.configs['engine'].get('options', None),
57+
self.configs['tools'][tool].get('options', None),
58+
self.configs['tools'][tool]['container'],
59+
name
60+
]
61+
return ' '.join(list(filter(None, oci)))
62+
return name
63+
64+
def get_tools(self):
65+
"""Returns the list of configured tools."""
66+
return sorted(list(self.configs['tools'].keys()))
67+
68+
def dump(self):
69+
"""Dumps the configuration in YAML format (debug purpouses)."""
70+
return dump(self.configs)
71+
72+
def set_engine(self, engine):
73+
"""Set the OCI engine."""
74+
self.configs['engine']['name'] = engine
75+
76+
def unset_engine(self):
77+
"""Unset the OCI engine. """
78+
self.configs['engine']['name'] = None
79+
80+
def set_volumes(self, volumes):
81+
"""Set the volumes of the OCI engine."""
82+
self.configs['engine']['volumes'] = volumes
83+
84+
def set_work(self, work):
85+
"""Set the working directory inside the container."""
86+
self.configs['engine']['work'] = work
87+
88+
def set_general_options(self, options):
89+
"""Set options shared by all the containers."""
90+
self.configs['engine']['options'] = options
91+
92+
def set_container(self, tool, container):
93+
"""Set the container of the specified tool."""
94+
self.configs['tools'][tool]['container'] = container
95+
96+
def set_name(self, tool, name):
97+
"""Set the name of the specified tool."""
98+
self.configs['tools'][tool]['name'] = name
99+
100+
def set_particular_options(self, tool, options):
101+
"""Set options for a particular container."""
102+
self.configs['tools'][tool]['options'] = options

0 commit comments

Comments
 (0)