Skip to content

Commit

Permalink
apply black, add flake8 rules
Browse files Browse the repository at this point in the history
  • Loading branch information
luerhard committed Nov 23, 2023
1 parent 9102399 commit 2bb0194
Show file tree
Hide file tree
Showing 13 changed files with 205 additions and 102 deletions.
4 changes: 4 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[flake8]
per-file-ignores =
__init__.py:F401
max-line-length = 100
5 changes: 0 additions & 5 deletions .gitlab-ci.yml

This file was deleted.

93 changes: 65 additions & 28 deletions pyintergraph/Graph.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
from collections import defaultdict, abc
import numbers
from .infer import infer_type, get_c_type
from .infer import infer_type
from .exceptions import PyIntergraphCompatibilityException


class InterGraph:
"""This defines a interchangeable format that can be read in by the 'from_'-classmethods
and convert the interchangeable format the package formats with the 'to_'-methods
and convert the interchangeable format the package formats with the 'to_'-methods
"""

def __init__(self, nodes, node_labels, node_attributes, edges, edge_attributes, is_directed):
def __init__(
self, nodes, node_labels, node_attributes, edges, edge_attributes, is_directed
):
self.nodes = nodes
self.node_labels = node_labels
self.node_attributes = node_attributes
Expand Down Expand Up @@ -53,7 +56,9 @@ def from_networkx(cls, nxG):

edges = [(label_map[u], label_map[v]) for u, v in zip(u_s, v_s)]

return cls(nodes, node_labels, node_attributes, edges, edge_attributes, is_directed)
return cls(
nodes, node_labels, node_attributes, edges, edge_attributes, is_directed
)

@classmethod
def from_graph_tool(cls, gtG, labelname=None):
Expand All @@ -76,16 +81,20 @@ def from_graph_tool(cls, gtG, labelname=None):

def create_nodes(g):
for v in g.vertices():
attrs = {attr: g.vertex_properties[attr][v]
for attr in g.vertex_properties.keys()
if not attr == labelname}
attrs = {
attr: g.vertex_properties[attr][v]
for attr in g.vertex_properties.keys()
if not attr == labelname
}
yield (v, attrs)

def create_edges(g):
for e in g.edges():
attrs = {attr: g.edge_properties[attr][e]
for attr in g.edge_properties.keys()
if not attr == labelname}
attrs = {
attr: g.edge_properties[attr][e]
for attr in g.edge_properties.keys()
if not attr == labelname
}
yield ((e.source(), e.target()), attrs)

try:
Expand All @@ -106,8 +115,12 @@ def create_edges(g):
# create name-map for nodes
nodemap = {v: i for v, i in zip(gtG.vertices(), gtG.get_vertices())}
if labelname:
node_labels = {v: label for v, label in
zip(gtG.get_vertices(), gtG.vertex_properties[labelname])}
node_labels = {
v: label
for v, label in zip(
gtG.get_vertices(), gtG.vertex_properties[labelname]
)
}
nodes = list(node_labels.keys())
else:
node_labels = {i: i for i in gtG.get_vertices()}
Expand All @@ -126,11 +139,14 @@ def create_edges(g):
else:
edges = [(nodemap[u], nodemap[v]) for u, v in gt_edges]

return cls(nodes, node_labels, node_attributes, edges, edge_attributes, is_directed)
return cls(
nodes, node_labels, node_attributes, edges, edge_attributes, is_directed
)

@classmethod
def from_igraph(cls, iG):
import igraph

"""Converts igraph-Graph to Graph object
"""

Expand Down Expand Up @@ -159,7 +175,14 @@ def from_igraph(cls, iG):
else:
node_labels[node] = node

return cls(list(nodes), node_labels, node_attributes, list(edges), edge_attributes, is_directed)
return cls(
list(nodes),
node_labels,
node_attributes,
list(edges),
edge_attributes,
is_directed,
)

def to_networkx(self):
"""
Expand Down Expand Up @@ -188,7 +211,9 @@ def to_networkx(self):
else:
nxG = nx.MultiDiGraph()

nxG.add_nodes_from(zip((self.node_labels[n] for n in self.nodes), self.node_attributes))
nxG.add_nodes_from(
zip((self.node_labels[n] for n in self.nodes), self.node_attributes)
)

for edge, edge_attr in zip(self.edges, self.edge_attributes):
u, v = edge
Expand Down Expand Up @@ -221,23 +246,27 @@ def to_graph_tool(self, labelname=None):
node_property_type_assertion = defaultdict(set)

for nx_node, data in zip(self.nodes, self.node_attributes):

v = gtG.add_vertex()
if labelname:
attrs[labelname][v] = self.node_labels[nx_node]
nodes[nx_node] = v

for key, val in data.items():

# Single Type assertion
node_property_type_assertion[key].add(type(val))
if len(node_property_type_assertion[key]) > 1:
raise Exception(f"Type not equal for all nodes on Node-Attribute {key}, \
types found: {node_property_type_assertion[key]}")
raise Exception(
f"Type not equal for all nodes on Node-Attribute {key}, \
types found: {node_property_type_assertion[key]}"
)

if key not in attrs:
as_vector = isinstance(val, abc.Iterable) and not isinstance(val, str)
attrs[key] = gtG.new_vertex_property(infer_type(val, as_vector=as_vector))
as_vector = isinstance(val, abc.Iterable) and not isinstance(
val, str
)
attrs[key] = gtG.new_vertex_property(
infer_type(val, as_vector=as_vector)
)

attrs[key][v] = val

Expand All @@ -250,16 +279,21 @@ def to_graph_tool(self, labelname=None):
u, v = e
edge = gtG.add_edge(nodes[u], nodes[v])
for key, val in data.items():

# Single Type assertion
edge_property_assertion[key].add(type(val))
if len(edge_property_assertion[key]) > 1:
raise Exception(f"Type not equal for all edges on Edge-Attribute {key}, \
types found: {edge_property_assertion[key]}")
raise Exception(
f"Type not equal for all edges on Edge-Attribute {key}, \
types found: {edge_property_assertion[key]}"
)

if key not in attrs:
as_vector = isinstance(val, abc.Iterable) and not isinstance(val, str)
attrs[key] = gtG.new_edge_property(infer_type(val, as_vector=as_vector))
as_vector = isinstance(val, abc.Iterable) and not isinstance(
val, str
)
attrs[key] = gtG.new_edge_property(
infer_type(val, as_vector=as_vector)
)

attrs[key][edge] = val

Expand Down Expand Up @@ -288,8 +322,11 @@ def to_igraph(self):
iG.add_vertex(self.node_labels[node], **attr)
else:
if "name" in attr:
raise PyIntergraphCompatibilityException("Your network seems to have 'name' as a node attribute."
"This is a reserved keyword for node labels in python-igraph. You cannot use that !")
raise PyIntergraphCompatibilityException(
"Your network seems to have 'name' as a node attribute. "
"This is a reserved keyword for node labels in python-igraph. "
"You cannot use that !"
)
iG.add_vertex()
iG.vs[i].update_attributes(name=self.node_labels[node], **attr)

Expand Down
4 changes: 2 additions & 2 deletions pyintergraph/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
class PyIntergraphInferException(Exception):

def __init__(self, msg):
self.msg = msg

def __str__(self):
return self.msg


class PyIntergraphCompatibilityException(Exception):
pass
pass
8 changes: 7 additions & 1 deletion pyintergraph/funcs.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
from .Graph import InterGraph


def nx2gt(nxG, labelname=None):
G = InterGraph.from_networkx(nxG)
return G.to_graph_tool(labelname=labelname)


def nx2igraph(nxG):
G = InterGraph.from_networkx(nxG)
return G.to_igraph()


def gt2nx(gtG, labelname=None):
G = InterGraph.from_graph_tool(gtG, labelname=labelname)
return G.to_networkx()


def gt2igraph(gtG, labelname=None):
G = InterGraph.from_graph_tool(gtG, labelname=labelname)
return G.to_igraph()


def igraph2nx(iG):
G = InterGraph.from_igraph(iG)
return G.to_networkx()


def igraph2gt(iG, labelname=None):
G = InterGraph.from_igraph(iG)
return G.to_graph_tool(labelname=labelname)
return G.to_graph_tool(labelname=labelname)
33 changes: 19 additions & 14 deletions pyintergraph/infer.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from collections import abc
from functools import lru_cache
import numbers

import pyintergraph


def get_c_type(v):
if isinstance(v, str):
return "string"
Expand All @@ -20,7 +20,8 @@ def get_c_type(v):
return "int64_t"
else:
raise pyintergraph.PyIntergraphInferException(
"Value {v} does not fit in c++ datatypes of graph_tools !")
"Value {v} does not fit in c++ datatypes of graph_tools !"
)
elif isinstance(v, float):
if pyintergraph.USE_LONG_DOUBLE:
return "long double"
Expand All @@ -32,11 +33,12 @@ def get_c_type(v):
else:
return "double"
else:
raise pyintergraph.PyIntergraphInferException("Non supported Type in Attributes!")
raise pyintergraph.PyIntergraphInferException(
"Non supported Type in Attributes!"
)


def get_best_fitting_type(c_types):

if "object" in c_types:
return "python::object"
elif "string" in c_types:
Expand All @@ -56,23 +58,26 @@ def get_best_fitting_type(c_types):
return "uint8_t"




def infer_type(values, as_vector=True):

# check for types in Iterable
if isinstance(values, abc.Iterable) and not isinstance(values, str) and not isinstance(values, dict):
if (
isinstance(values, abc.Iterable)
and not isinstance(values, str)
and not isinstance(values, dict)
):
c_types = {get_c_type(v) for v in values}
else:
c_types = get_c_type(values)

number_types = ["long double", "double", "long", "int", "short", "bool"]
if any(t in number_types for t in c_types) and not all(t in number_types for t in c_types):
raise pyintergraph.PyIntergraphInferException("Cannot mix datatypes ! Found {}".format(c_types))

number_types = ["long double", "double", "long", "int", "short", "bool"]
if any(t in number_types for t in c_types) and not all(
t in number_types for t in c_types
):
raise pyintergraph.PyIntergraphInferException(
"Cannot mix datatypes ! Found {}".format(c_types)
)

best_fit = get_best_fitting_type(c_types)
if as_vector:
return f"vector<{best_fit}>"
return best_fit


19 changes: 19 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ net = ["networkx", "python-igraph"]
pytest = ">=7"
pytest-cov = ">=4"

[tool.black]
line-length = 100
include = '\.pyi?$'
exclude = '''
/(
\.git
| \.hg
| \.mypy_cache
| \.tox
| _build
| buck-out
| build
| dist
)/
'''

[tool.flake8]
max-line-length=100

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Loading

0 comments on commit 2bb0194

Please sign in to comment.