Skip to content

Commit 90557b4

Browse files
committed
openflow: add configure.py
A class, and a helper that uses it, to configure the OCI engine, containers and tools names.
1 parent 5a44906 commit 90557b4

File tree

14 files changed

+371
-9
lines changed

14 files changed

+371
-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: global-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: local-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 a global options:')
23+
cfg.set_global_options('--global 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 a local options:')
35+
cfg.set_local_options('ghdl', '--local 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: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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+
userfile = os.getenv('OPENFLOW_FILE')
35+
homefile = os.path.join(os.path.expanduser('~'), filename)
36+
projfile = os.path.join(os.path.dirname(__file__), 'configure.yml')
37+
if userfile is not None and os.path.exists(userfile):
38+
filepath = userfile
39+
elif os.path.exists(filename):
40+
filepath = filename
41+
elif os.path.exists(homefile):
42+
filepath = homefile
43+
else:
44+
filepath = projfile
45+
self.configs = {}
46+
with open(filepath, 'r') as file:
47+
self.configs = safe_load(file)
48+
49+
def get_command(self, tool):
50+
"""Get the command-line needed to run a tool."""
51+
engine = self.configs['engine']['name']
52+
name = self.configs['tools'][tool]['name']
53+
if engine is not None and os.getenv('OPENFLOW_OFF') is None:
54+
oci = [
55+
engine,
56+
'run --rm',
57+
'-v ' + (' -v ').join(self.configs['engine']['volumes']),
58+
'-w ' + self.configs['engine']['work'],
59+
self.configs['engine'].get('options', None),
60+
self.configs['tools'][tool].get('options', None),
61+
self.configs['tools'][tool]['container'],
62+
name
63+
]
64+
return ' '.join(list(filter(None, oci)))
65+
return name
66+
67+
def get_tools(self):
68+
"""Returns the list of configured tools."""
69+
return sorted(list(self.configs['tools'].keys()))
70+
71+
def dump(self):
72+
"""Dumps the configuration in YAML format (debug purpouses)."""
73+
return dump(self.configs)
74+
75+
def set_engine(self, engine):
76+
"""Set the OCI engine."""
77+
self.configs['engine']['name'] = engine
78+
79+
def unset_engine(self):
80+
"""Unset the OCI engine. """
81+
self.configs['engine']['name'] = None
82+
83+
def set_volumes(self, volumes):
84+
"""Set the volumes of the OCI engine."""
85+
self.configs['engine']['volumes'] = volumes
86+
87+
def set_work(self, work):
88+
"""Set the working directory inside the container."""
89+
self.configs['engine']['work'] = work
90+
91+
def set_global_options(self, options):
92+
"""Set options shared by all the containers."""
93+
self.configs['engine']['options'] = options
94+
95+
def set_container(self, tool, container):
96+
"""Set the container of the specified tool."""
97+
self.configs['tools'][tool]['container'] = container
98+
99+
def set_name(self, tool, name):
100+
"""Set the name of the specified tool."""
101+
self.configs['tools'][tool]['name'] = name
102+
103+
def set_local_options(self, tool, options):
104+
"""Set options for a particular container."""
105+
self.configs['tools'][tool]['options'] = options

0 commit comments

Comments
 (0)