-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Additional API updates #103
base: redesign-staging
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from drf_yasg.utils import swagger_auto_schema | ||
from rest_framework import serializers | ||
from rest_framework.decorators import action | ||
from rest_framework.response import Response | ||
from rest_framework.viewsets import ModelViewSet | ||
|
||
from uvdat.core.models import Network | ||
from uvdat.core.rest.access_control import GuardianFilter, GuardianPermission | ||
from uvdat.core.rest.serializers import NetworkSerializer | ||
|
||
|
||
class GCCQueryParamSerializer(serializers.Serializer): | ||
exclude_nodes = serializers.RegexField(r'^\d+(,\s?\d+)*$') | ||
|
||
|
||
class NetworkViewSet(ModelViewSet): | ||
queryset = Network.objects.all() | ||
serializer_class = NetworkSerializer | ||
permission_classes = [GuardianPermission] | ||
filter_backends = [GuardianFilter] | ||
lookup_field = 'id' | ||
|
||
@swagger_auto_schema(query_serializer=GCCQueryParamSerializer) | ||
@action(detail=True, methods=['get']) | ||
def gcc(self, request, **kwargs): | ||
network = self.get_object() | ||
|
||
# Validate and de-serialize query params | ||
serializer = GCCQueryParamSerializer(data=request.query_params) | ||
serializer.is_valid(raise_exception=True) | ||
exclude_nodes = [int(n) for n in serializer.validated_data['exclude_nodes'].split(',')] | ||
|
||
gcc = network.get_gcc(excluded_nodes=exclude_nodes) | ||
return Response(gcc, status=200) | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ def create_network(vector_data, network_options): | |
dataset = vector_data.dataset | ||
Network.objects.filter(vector_data__dataset=dataset).delete() | ||
network = Network.objects.create( | ||
name=dataset.name + ' Network', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we currently constraining Networks to be one-to-one with datasets? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, do you think that we should add numbering to this name string to account for multi-network datasets? |
||
category=dataset.category, | ||
vector_data=vector_data, | ||
metadata={'source': 'Parsed from GeoJSON.'}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import itertools | ||
|
||
import pytest | ||
|
||
from uvdat.core.models import Dataset, Network, NetworkNode, Project | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_rest_dataset_networks_no_network( | ||
authenticated_api_client, dataset: Dataset, project: Project | ||
): | ||
project.datasets.add(dataset) | ||
resp = authenticated_api_client.get(f'/api/v1/datasets/{dataset.id}/networks/') | ||
assert resp.status_code == 200 | ||
assert not resp.json() | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_rest_dataset_networks(authenticated_api_client, project: Project, network_edge): | ||
network = network_edge.network | ||
dataset = network.vector_data.dataset | ||
project.datasets.add(dataset) | ||
assert network_edge.from_node != network_edge.to_node | ||
|
||
resp = authenticated_api_client.get(f'/api/v1/datasets/{dataset.id}/networks/') | ||
assert resp.status_code == 200 | ||
|
||
data: list[dict] = resp.json() | ||
assert len(data) == 1 | ||
|
||
data: dict = data[0] | ||
assert len(data['nodes']) == 2 | ||
assert len(data['edges']) == 1 | ||
|
||
|
||
@pytest.mark.django_db | ||
def test_rest_network_gcc_empty(authenticated_api_client, user, project: Project, network: Network): | ||
dataset = network.vector_data.dataset | ||
project.set_owner(user) | ||
project.datasets.add(dataset) | ||
resp = authenticated_api_client.get(f'/api/v1/networks/{network.id}/gcc/?exclude_nodes=1') | ||
|
||
assert resp.status_code == 200 | ||
assert resp.json() == [] | ||
|
||
|
||
@pytest.mark.parametrize('group_sizes', [(3, 2), (20, 3)]) | ||
@pytest.mark.django_db | ||
def test_rest_network_gcc( | ||
authenticated_api_client, | ||
user, | ||
project: Project, | ||
network: Network, | ||
network_edge_factory, | ||
network_node_factory, | ||
group_sizes, | ||
): | ||
dataset = network.vector_data.dataset | ||
project.set_owner(user) | ||
project.datasets.add(dataset) | ||
group_a_size, group_b_size = group_sizes | ||
|
||
# Create two groups of nodes that fully connected | ||
group_a = [network_node_factory(network=network) for _ in range(group_a_size)] | ||
for from_node, to_node in itertools.combinations(group_a, 2): | ||
network_edge_factory(network=network, from_node=from_node, to_node=to_node) | ||
|
||
group_b = [network_node_factory(network=network) for _ in range(group_b_size)] | ||
for from_node, to_node in itertools.combinations(group_b, 2): | ||
network_edge_factory(network=network, from_node=from_node, to_node=to_node) | ||
|
||
# Join these two groups by a single node | ||
connecting_node: NetworkNode = network_node_factory(network=network) | ||
network_edge_factory(network=network, from_node=group_a[0], to_node=connecting_node) | ||
network_edge_factory(network=network, from_node=group_b[0], to_node=connecting_node) | ||
|
||
# Network should look like this | ||
# * * | ||
# | | | ||
# * ---- * ---- * | ||
# | | ||
# * | ||
|
||
resp = authenticated_api_client.get( | ||
f'/api/v1/networks/{network.id}/gcc/?exclude_nodes={connecting_node.id}' | ||
) | ||
|
||
larger_group: list[NetworkNode] = max(group_a, group_b, key=len) | ||
assert resp.status_code == 200 | ||
assert sorted(resp.json()) == sorted([n.id for n in larger_group]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably best to use a serializer here, but I understand this is just relocated code. Not a huge deal imo.