Skip to content
Open
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
82 changes: 82 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Python CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest

services:
neo4j:
image: neo4j:3.5
ports:
- 7687:7687 # Bolt port
- 7474:7474 # Web
options: >
--env NEO4J_AUTH=neo4j/testpassword
--env NEO4J_dbms_memory_heap_initial__size=512m
--env NEO4J_dbms_memory_heap_max__size=1G

steps:
- uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'

- name: Install dependencies
run: |
curl -sSL https://install.python-poetry.org | python3 -
poetry install

- name: Wait for Neo4j to be ready
run: |
echo "Waiting for Neo4j to start..."
sleep 30

- name: Run Tests
env:
NEO4J_HTTP_PORT: 7474
NEO4J_BOLT_PORT: 7687
NEO4J_HOSTNAME: localhost
NEO4J_USER: neo4j
NEO4J_PASSWORD: testpassword
run: |
# Ensure we can connect to Neo4j
curl -I http://localhost:7474
poetry run python -m unittest discover -s tests
build:
needs: test # Only run after tests succeed
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'

- name: Install Poetry
run: curl -sSL https://install.python-poetry.org | python3 -

- name: Install Dependencies
run: poetry install

- name: Build the package
run: poetry build

- name: List files in dist/
run: ls -al dist

- name: 'Upload Artifact'
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: dist/
retention-days: 5
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
.nox
/.nox
.mypy_cache
htmlcov/
.tox/
.coverage
Expand Down Expand Up @@ -91,4 +94,5 @@ env

# PyCharm project settings
.idea
./.idea

116 changes: 115 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,125 @@
# python-norduniclient

[![PyPI](https://img.shields.io/pypi/v/norduniclient.svg)](https://pypi.python.org/pypi/norduniclient)

Neo4j database client for NORDUnet network inventory

## Compatibility

| Tools | Version |
| ----------- | --------- |
| neo4j DB | 4.4.x |
| neo4j | 4.4.x |
| neomodel | 5.0.x |

## Setup

```
poetry shell
poetry install
```

## Running tests

Add the following environment variables:

```env
NEO4J_HTTP_PORT=7474
NEO4J_BOLT_PORT=7687
NEO4J_HOSTNAME=xx
NEO4J_USER=xx
NEO4J_PASSWORD=xx
```

and run

```bash
poetry run python -m unittest discover
```

or save the environment variables in a local file `.env` and run it with [dotenvx](https://dotenvx.com/) as follows:

```bash
dotenvx run -- poetry run python -m unittest discover
```
python -m unittest discover -s norduniclient/tests/

or

```bash
nox -rs tests
```

```bash
nox -rs tests_dotenv
```

## Installation

```bash
pip install norduniclient
```

python3 -m pip install --index-url <https://platform.sunet.se/api/packages/benedith/pypi/simple/> --extra-index-url <https://pypi.org/simple/> norduniclient

python3 -m pip install -i <https://test.pypi.org/simple/> --extra-index-url <https://pypi.org/simple/> jolieprinter

## Usage

```python
import norduniclient as nc

NODE_META_TYPE_CHOICES = zip(nc.META_TYPES, nc.META_TYPES)

print("nc.META_TYPES=", nc.META_TYPES)
```

### Poetry guide

```
poetry run python [operation]
```

### Add depenency

#### Add a new lib

```bash
poetry add <library>
```

#### Remove a lib

```bash
poetry remove <library>
```

#### Get venv path

```bash
poetry run which python
```

#### Show dependencies

```bash
poetry show
```

```bash
poetry run pip list
```

#### List configuratiom

```bash
poetry config --list
```

### Publish

```bash
poetry config repositories.pypi https://upload.pypi.org/legacy/
poetry config pypi-token.pypi [token]
poetry publish --build --repository pypi
poetry publish --build --repository testpypi
```
52 changes: 52 additions & 0 deletions norduniclient-package.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# python-norduniclient

[![PyPI](https://img.shields.io/pypi/v/norduniclient.svg)](https://pypi.python.org/pypi/norduniclient)

Neo4j database client for NORDUnet network inventory

## Compatibility

| Tools | Version |
| ----------- | --------- |
| neo4j DB | 4.4.x |
| neo4j | 4.4.x |
| neomodel | 5.0.x |

## Setup

```bash
poetry shell
poetry install
```

## Running tests

Add the following environment variables:

```bash
NEO4J_HTTP_PORT=7474
NEO4J_BOLT_PORT=7687
NEO4J_HOSTNAME=xx
NEO4J_USER=xx
NEO4J_PASSWORD=xx
```

```bash
poetry run python -m unittest discover
```

## Installation

```bash
pip install norduniclient
```

## Usage

```python
import norduniclient as nc

NODE_META_TYPE_CHOICES = zip(nc.META_TYPES, nc.META_TYPES)

print("nc.META_TYPES=", nc.META_TYPES)
```
1 change: 0 additions & 1 deletion norduniclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,3 @@
graphdb = GraphDB.get_instance()

neo4jdb = graphdb.manager # Works as the old neo4jdb

20 changes: 11 additions & 9 deletions norduniclient/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@

from __future__ import absolute_import

from neo4j.v1 import GraphDatabase, basic_auth
from neo4j.exceptions import ProtocolError, ClientError
from neo4j import GraphDatabase
from neo4j.exceptions import DatabaseError, ClientError
from neo4j.api import basic_auth
from norduniclient import exceptions
from norduniclient import models

Expand Down Expand Up @@ -118,7 +119,7 @@ def init_db(uri=NEO4J_URI, username=NEO4J_USERNAME, password=NEO4J_PASSWORD, enc
logger.error('Could not create index for Neo4j database: {!s}'.format(uri))
raise e
return manager
except ProtocolError as e:
except DatabaseError as e:
logger.warning('Could not connect to Neo4j database: {!s}'.format(uri))
raise e

Expand All @@ -138,10 +139,11 @@ def get_db_driver(uri, username=None, password=None, encrypted=True, max_pool_si
:param trust: Trust cert on first use (0) or do not accept unknown cert (1)
:type trust: Integer
:return: Neo4j driver
:rtype: neo4j.v1.session.Driver
:rtype: neo4j.session.Driver
"""

return GraphDatabase.driver(uri, auth=basic_auth(username, password), encrypted=encrypted,
max_pool_size=max_pool_size, trust=trust)
max_connection_pool_size=max_pool_size, trust='TRUST_ALL_CERTIFICATES')


def query_to_dict(manager, query, **kwargs):
Expand Down Expand Up @@ -216,7 +218,7 @@ def get_node(manager, handle_id):
:type manager: norduniclient.contextmanager.Neo4jDBSessionManager
:type handle_id: str|unicode

:rtype: dict|neo4j.v1.types.Node
:rtype: dict|neo4j.types.Node
"""
q = 'MATCH (n:Node { handle_id: $handle_id }) RETURN n'

Expand All @@ -233,7 +235,7 @@ def get_node_bundle(manager, handle_id=None, node=None):
:param handle_id: Unique id
:type handle_id: str|unicode
:param node: Node object
:type node: neo4j.v1.types.Node
:type node: neo4j.types.Node
:return: dict
"""
if not node:
Expand Down Expand Up @@ -283,7 +285,7 @@ def get_relationship(manager, relationship_id):
:type manager: norduniclient.contextmanager.Neo4jDBSessionManager
:type relationship_id: int

:rtype int|neo4j.v1.types.Relationship
:rtype int|neo4j.types.Relationship
"""
q = """
MATCH ()-[r]->()
Expand Down Expand Up @@ -674,7 +676,7 @@ def get_node_model(manager, handle_id=None, node=None):
:param handle_id: Nodes handle id
:type handle_id: str|unicode
:param node: Node object
:type node: neo4j.v1.types.Node
:type node: neo4j.types.Node
:return: Node model
:rtype: models.BaseNodeModel or sub class of models.BaseNodeModel
"""
Expand Down
6 changes: 3 additions & 3 deletions norduniclient/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def __init__(self, handle_id1, meta_type1, handle_id2, meta_type2, relationship_
self.meta_type1 = meta_type1
self.meta_type2 = meta_type2
self.relationship_type = relationship_type

def __str__(self):
node1_str = '{meta_type} Node ({handle_id})'.format(meta_type=self.meta_type1, handle_id=self.handle_id1)
node2_str = '{meta_type} Node ({handle_id})'.format(meta_type=self.meta_type2, handle_id=self.handle_id2)
Expand All @@ -32,7 +32,7 @@ class MetaLabelNamingError(Exception):
"""
def __init__(self, name):
self.error = 'A meta label can not be named {name}.'.format(name=name)

def __str__(self):
return self.error

Expand All @@ -44,7 +44,7 @@ class NoMetaLabelFound(Exception):
"""
def __init__(self, handle_id):
self.handle_id = handle_id

def __str__(self):
return 'Node with handle_id {handle_id} has no meta label.'.format(handle_id=self.handle_id)

Expand Down
2 changes: 1 addition & 1 deletion norduniclient/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ def get_dependent_as_types(self):
WITH direct, deps, services, paths, oms, [n in deps WHERE n:Optical_Link] as links
RETURN direct, services, paths, oms, links
"""

return core.query_to_dict(self.manager, q, handle_id=self.handle_id)


Expand Down
Loading