Skip to content
This repository was archived by the owner on Jun 6, 2025. It is now read-only.

Commit a94ccae

Browse files
Gh-35: Refactor tests to use tox and pytest (#36)
* Refactor test suite to use tox and pytest, and have separate directories for unit and integration tests. Update READMEs, and fishbowl scripts and jinja templates. Refactor fishbowl to generate import strings. * Copyright and licence
1 parent e78aac8 commit a94ccae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+3431
-2767
lines changed

.github/workflows/continuous-integration.yaml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,14 @@ jobs:
5050
curl -o jetty-runner.jar https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.52.v20230823/jetty-runner-9.4.52.v20230823.jar
5151
curl -o road-traffic-rest.war https://repo1.maven.org/maven2/uk/gov/gchq/gaffer/road-traffic-rest/$gafferVersion/road-traffic-rest-$gafferVersion.war
5252
java \
53-
-Dgaffer.storeProperties=src/test/road-traffic-example/store.properties \
54-
-Dgaffer.graph.config=src/test/road-traffic-example/graphConfig.json \
55-
-Dgaffer.schemas=src/test/road-traffic-example/schema \
56-
-DroadTraffic.dataLoader.dataPath=src/test/road-traffic-example/roadTrafficSampleData.csv \
53+
-Dgaffer.storeProperties=tests/road-traffic-example/store.properties \
54+
-Dgaffer.graph.config=tests/road-traffic-example/graphConfig.json \
55+
-Dgaffer.schemas=tests/road-traffic-example/schema \
56+
-DroadTraffic.dataLoader.dataPath=tests/road-traffic-example/roadTrafficSampleData.csv \
5757
-jar jetty-runner.jar --path rest road-traffic-rest.war &
5858
sleep 1m
5959
6060
- name: Run Python tests
61-
run: python3 -m unittest discover -s src
61+
run: |
62+
python3 -m pip install ".[dev]"
63+
python3 -m tox

.github/workflows/update-gaffer-version.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
run: |
4040
newVersion=${{ github.event.inputs.version }}
4141
curl -o spring-rest.jar https://repo.maven.apache.org/maven2/uk/gov/gchq/gaffer/spring-rest/$newVersion/spring-rest-$newVersion-exec.jar
42-
java -Dgaffer.schemas=src/test/road-traffic-example/schema -Dgaffer.storeProperties=src/test/road-traffic-example/federatedStore.properties -Dgaffer.graph.config=src/test/road-traffic-example/federatedGraphConfig.json -jar spring-rest.jar &
42+
java -Dgaffer.schemas=tests/road-traffic-example/schema -Dgaffer.storeProperties=tests/road-traffic-example/federatedStore.properties -Dgaffer.graph.config=tests/road-traffic-example/federatedGraphConfig.json -jar spring-rest.jar &
4343
sleep 1m
4444
python src/generate.py
4545
rm spring-rest.jar

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ celerybeat.pid
9494

9595
# Environments
9696
.env
97-
.venv
97+
.venv*
9898
.venv-python-example
9999
env/
100100
venv/

README.md

Lines changed: 127 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,127 @@
1-
<img align="right" width="200" height="auto" src="https://github.com/gchq/Gaffer/raw/develop/logos/logo.png">
2-
3-
# Gaffer Python Client
4-
5-
![ci](https://github.com/gchq/gafferpy/actions/workflows/continuous-integration.yaml/badge.svg)
6-
[<img src="https://img.shields.io/badge/docs-passing-success.svg?logo=readthedocs">](https://gchq.github.io/gafferpy/)
7-
8-
## Features
9-
10-
- Persistently connect to a Gaffer rest api to run operations
11-
- Connect using PKI certificates and SSL
12-
- Generate Python client code for custom Operations, Predicates, Binary Operators and Functions
13-
- Turn existing json queries into Python objects
14-
15-
## Installation
16-
17-
Gafferpy requires Python 3.6+. We don't currently release gafferpy on pypi, but you can install it over ssh with:
18-
19-
```bash
20-
pip install git+https://github.com/gchq/gafferpy.git
21-
```
22-
23-
Or if you have the source code locally and want any changes you make reflected in your installation, you can run:
24-
25-
```bash
26-
pip install -e .
27-
```
28-
29-
## Quick Start
30-
31-
The python shell connects to a running Gaffer REST API.
32-
You can start the Gaffer road-traffic-demo rest server from the Gaffer repository, using the command:
33-
34-
```bash
35-
mvn clean install -pl :road-traffic-demo -Proad-traffic-demo,quick
36-
```
37-
38-
```python
39-
# Import the client library and connector
40-
from gafferpy import gaffer as g
41-
from gafferpy import gaffer_connector
42-
43-
# Instantiate a connector
44-
gc = gaffer_connector.GafferConnector("http://localhost:8080/rest/latest")
45-
46-
# You can use the connector to perform get requests
47-
schema = gc.execute_get(g.GetSchema())
48-
49-
# And also run operations
50-
elements = gc.execute_operation(
51-
operation=g.GetAllElements()
52-
)
53-
54-
# Multiple operations
55-
elements = gc.execute_operations(
56-
operations=[
57-
g.GetAllElements(),
58-
g.Limit(result_limit=3)
59-
]
60-
)
61-
62-
# And operation chains
63-
elements = gc.execute_operation_chain(
64-
operation_chain=g.OperationChain(
65-
operations=[
66-
g.GetAllElements(),
67-
g.Limit(
68-
truncate=True,
69-
result_limit=3
70-
)
71-
]
72-
)
73-
)
74-
```
75-
76-
See [operation examples](https://gchq.github.io/gaffer-doc/v1docs/getting-started/operations/contents) for more examples of operations in python.
77-
78-
## Coding Style
79-
Please ensure that your coding style is consistent with the rest of the Gaffer project. Guides on the coding style for Gaffer can be found [here](https://gchq.github.io/gaffer-doc/latest/ways-of-working/#coding-style)
80-
81-
## Testing
82-
83-
```bash
84-
# To run all of the tests, first deploy the road traffic example
85-
# This needs to be done from the Gaffer java repository
86-
mvn clean install -pl :road-traffic-demo -Proad-traffic-demo,quick
87-
88-
# Then run
89-
python -m unittest discover
90-
```
91-
92-
## Building the documentation
93-
94-
To build the docs locally, assuming you have Python installed, install the docs dependencies:
95-
```bash
96-
cd docs
97-
pip install -r requirements.txt
98-
```
99-
100-
Then use the sphinx Makefile:
101-
```bash
102-
make html
103-
```
104-
105-
## License
106-
107-
Copyright 2016-2022 Crown Copyright
108-
109-
Licensed under the Apache License, Version 2.0 \(the "License"\); you may not use this file except in compliance with the License. You may obtain a copy of the License at
110-
111-
[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
112-
113-
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
1+
<img align="right" width="200" height="auto" src="https://github.com/gchq/Gaffer/raw/develop/logos/logo.png">
2+
3+
# Gaffer Python Client
4+
5+
![ci](https://github.com/gchq/gafferpy/actions/workflows/continuous-integration.yaml/badge.svg)
6+
[<img src="https://img.shields.io/badge/docs-passing-success.svg?logo=readthedocs">](https://gchq.github.io/gafferpy/)
7+
8+
## Features
9+
10+
- Persistently connect to a Gaffer rest api to run operations
11+
- Connect using PKI certificates and SSL
12+
- Generate Python client code for custom Operations, Predicates, Binary Operators and Functions
13+
- Turn existing json queries into Python objects
14+
15+
## Installation
16+
17+
`gafferpy` requires Python 3.6+. We do not currently release `gafferpy` on PyPI, but you can install it over ssh with:
18+
19+
```bash
20+
pip install git+https://github.com/gchq/gafferpy.git
21+
```
22+
23+
Or if you have the source code locally and want any changes you make reflected in your installation, you can run:
24+
25+
```bash
26+
pip install -e .
27+
```
28+
29+
## Quick Start
30+
31+
The Python shell connects to a running Gaffer REST API.
32+
You can start the Gaffer [`road-traffic-demo`](https://github.com/gchq/Gaffer/blob/master/example/road-traffic/README.md) REST server from the Gaffer repository, using the command:
33+
34+
```bash
35+
mvn clean install -pl :road-traffic-demo -Proad-traffic-demo,quick
36+
```
37+
To connect to the running Gaffer API from Python (more information on the Python shell can be found [here](https://gchq.github.io/gaffer-doc/latest/user-guide/apis/python-api/)):
38+
```python
39+
# Import the client library and connector
40+
from gafferpy import gaffer as g
41+
from gafferpy import gaffer_connector
42+
43+
# Instantiate a connector
44+
gc = gaffer_connector.GafferConnector("http://localhost:8080/rest/latest")
45+
```
46+
Then perform requests against it:
47+
```python
48+
# You can use the connector to perform GET requests
49+
schema = gc.execute_get(g.GetSchema())
50+
51+
# And also run operations
52+
elements = gc.execute_operation(
53+
operation=g.GetAllElements()
54+
)
55+
56+
# Multiple operations
57+
elements = gc.execute_operations(
58+
operations=[
59+
g.GetAllElements(),
60+
g.Limit(result_limit=3)
61+
]
62+
)
63+
64+
# And operation chains
65+
elements = gc.execute_operation_chain(
66+
operation_chain=g.OperationChain(
67+
operations=[
68+
g.GetAllElements(),
69+
g.Limit(
70+
truncate=True,
71+
result_limit=3
72+
)
73+
]
74+
)
75+
)
76+
```
77+
78+
See [Operations Guide](https://gchq.github.io/gaffer-doc/latest/reference/operations-guide/operations) for more examples of operations in Python.
79+
80+
## Developer Guide
81+
82+
### Coding Style
83+
Please ensure that your coding style is consistent with the rest of the Gaffer project. Guides on the coding style for `gafferpy` and Gaffer can be found [here](https://gchq.github.io/gaffer-doc/latest/development-guide/ways-of-working).
84+
85+
### Testing
86+
87+
The `gafferpy` tests are implemented using `tox` and `pytest`.
88+
To run the tests, install the `gafferpy` 'dev' extra:
89+
```bash
90+
pip install -e ".[dev]" # the quotes ensure compatibilty with zsh
91+
```
92+
This will install extra development dependecies for running tests and building documentation.
93+
94+
`gafferpy` has both unit tests and integration tests - the integration tests use the Road Traffic Example to test the Python API. If this is not running, the integration tests are skipped. It is advisable that the integration tests are run prior to any code commits to ensure they do not fail due to any code changes.
95+
96+
*For help starting the Road Traffic Example, see the [Quick Start](#quick-start) section above.*
97+
98+
To run the tests, execute the below from the root directory of `gafferpy`:
99+
```bash
100+
tox
101+
```
102+
By default, `tox` will and try run the tests in multiple test envs (different Python versions) - if they do not exist then they are skipped.
103+
To run the test for a specifc test env e.g. Python3.9, run:
104+
```bash
105+
tox -e py39
106+
```
107+
108+
### Building the documentation
109+
110+
To build the docs locally, assuming you have Make and Python installed, and `gafferpy` installed with the 'dev' extra:
111+
```bash
112+
cd docs
113+
make html
114+
```
115+
116+
### Generating the Python API
117+
`gafferpy` has the ability to regenerate the Python API based upon the Gaffer REST API that a `GafferConnector` object is pointing at - a more detailed description and examples of how to do this can be found [here](./src/fishbowl/README.md).
118+
119+
## License
120+
121+
Copyright 2016-2024 Crown Copyright
122+
123+
Licensed under the Apache License, Version 2.0 \(the "License"\); you may not use this file except in compliance with the License. You may obtain a copy of the License at
124+
125+
[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
126+
127+
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

setup.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import re
22
from codecs import open
3-
from os import path
3+
from pathlib import Path
44
from setuptools import setup, find_packages
55

66
###############################################################################
77

88
name = "gafferpy"
99
packages = find_packages(where="src")
10-
meta_path = path.join("src", "gafferpy", "__init__.py")
10+
meta_path = Path("src", "gafferpy", "__init__.py")
1111
keywords = ["class", "attribute", "boilerplate"]
1212
classifiers = [
1313
"Development Status :: 4 - Beta",
@@ -24,20 +24,27 @@
2424
python_requires = ">3.6"
2525
install_requires = []
2626
extras_require = {
27-
"requests": ["requests>=2.4.0"]
27+
"requests": ["requests>=2.4.0"],
28+
"dev": [
29+
"tox",
30+
"pytest",
31+
"requests>=2.4.0",
32+
"sphinx~=7.2.6",
33+
"sphinx-rtd-theme~=1.3.0"
34+
]
2835
}
2936

3037
###############################################################################
3138

32-
here = path.abspath(path.dirname(__file__))
39+
here = Path(__file__).parent
3340

3441

35-
def read(*parts):
42+
def read(parts):
3643
"""
3744
Build an absolute path from *parts* and and return the contents of the
3845
resulting file. Assume UTF-8 encoding.
3946
"""
40-
with open(path.join(here, *parts), "rb", "utf-8") as f:
47+
with open(here / parts, "rb", "utf-8") as f:
4148
return f.read()
4249

4350

@@ -54,14 +61,14 @@ def find_meta(meta):
5461
)
5562
if meta_match:
5663
return meta_match.group(1)
57-
raise RuntimeError("Unable to find __{meta}__ string.".format(meta=meta))
64+
raise RuntimeError(f"Unable to find __{meta}__ string.")
5865

5966

6067
version = find_meta("version")
6168
uri = find_meta("uri")
6269

6370
# Get the long description from the README.md file
64-
with open(path.join(here, "README.md"), encoding="utf-8") as f:
71+
with open(here / "README.md", encoding="utf-8") as f:
6572
long = f.read()
6673

6774
setup(

0 commit comments

Comments
 (0)