Skip to content

Commit

Permalink
Merge pull request #72 from isogeo/feature-attributes
Browse files Browse the repository at this point in the history
Improve Feature attributes management
  • Loading branch information
Guts committed Aug 7, 2019
2 parents fe0eb27 + be2f76c commit dc60d19
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 10 deletions.
54 changes: 45 additions & 9 deletions isogeo_pysdk/api/routes_feature_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,13 +321,16 @@ def update(

# -- Extra methods as helpers --------------------------------------------------
def import_from_dataset(
self, metadata_source: Metadata, metadata_dest: Metadata, mode: str = "simple"
self, metadata_source: Metadata, metadata_dest: Metadata, mode: str = "add"
) -> bool:
"""Import feature-attributes from another vector metadata.
:param Metadata metadata_source: metadata from which to import the attributes
:param Metadata metadata_dest: metadata where to import the attributes
:param str mode: [description], defaults to "simple"
:param str mode: mode of import, defaults to "add":
- 'add': add the attributes except those with a duplicated name
- 'update': update only the attributes with the same name
- 'update_or_add': update the attributes with the same name or create
:raises TypeError: if one metadata is not a vector
:raises ValueError: if mode is not one of accepted value
Expand All @@ -337,9 +340,9 @@ def import_from_dataset(
>>> md_source = isogeo.metadata.get(METADATA_UUID_SOURCE)
>>> md_dest = isogeo.metadata.get(METADATA_UUID_DEST)
>>> # launch import
>>> isogeo.metadata.attributes.import_from_dataset(md_source, md_dest, "simple")
>>> isogeo.metadata.attributes.import_from_dataset(md_source, md_dest, "add")
"""
accepted_modes = ("simple", "update")
accepted_modes = ("add", "update", "update_or_add")

# check metadata type
if (
Expand All @@ -360,7 +363,7 @@ def import_from_dataset(
attributes_dest_names = [attr.get("name") for attr in attributes_dest]

# according to the selected mode
if mode == "simple":
if mode == "add":
for attribute in attributes_source:
attribute = FeatureAttribute(**attribute)
# check if an attribute with the same name already exists and ignore it
Expand All @@ -380,13 +383,46 @@ def import_from_dataset(
)
elif mode == "update":
for attribute in attributes_source:
attribute = FeatureAttribute(**attribute)
attr_src = FeatureAttribute(**attribute)
# check if an attribute with the same name already exists, then update it
if attribute.name in attributes_dest_names:
self.update(metadata=metadata_dest, attribute=attribute)
if attr_src.name in attributes_dest_names:
attr_dst = FeatureAttribute(
**[
attr
for attr in attributes_dest
if attr.get("name") == attr_src.name
][0]
)
attr_dst.alias = attr_src.alias
attr_dst.dataType = attr_src.dataType
attr_dst.description = attr_src.description
attr_dst.language = attr_src.language
self.update(metadata=metadata_dest, attribute=attr_dst)
logger.debug(
"Attribute with the same name ({}) spotted. It has been updated.".format(
attribute.name
attr_dst.name
)
)
elif mode == "update_or_add":
for attribute in attributes_source:
attr_src = FeatureAttribute(**attribute)
# check if an attribute with the same name already exists, then update it
if attr_src.name in attributes_dest_names:
attr_dst = FeatureAttribute(
**[
attr
for attr in attributes_dest
if attr.get("name") == attr_src.name
][0]
)
attr_dst.alias = attr_src.alias
attr_dst.dataType = attr_src.dataType
attr_dst.description = attr_src.description
attr_dst.language = attr_src.language
self.update(metadata=metadata_dest, attribute=attr_dst)
logger.debug(
"Attribute with the same name ({}) spotted. It has been updated.".format(
attr_dst.name
)
)
else:
Expand Down
2 changes: 1 addition & 1 deletion isogeo_pysdk/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ def check_is_uuid(self, uuid_str: str):
"""
# check uuid type
if not isinstance(uuid_str, str):
logger.error(
logger.debug(
TypeError(
"'uuid_str' parameter expects a str value. Got: {}".format(
type(uuid_str)
Expand Down
174 changes: 174 additions & 0 deletions tests/test_feature_attributes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# -*- coding: UTF-8 -*-
#! python3

"""
Usage from the repo root folder:
```python
# for whole test
python -m unittest tests.test_feature_attributes
# for specific
python -m unittest tests.test_feature_attributes.TestFeatureAttributes.test_featureAttributes_create_basic
```
"""

# #############################################################################
# ########## Libraries #############
# ##################################

# Standard library
import logging
import urllib3
import unittest
from os import environ
from pathlib import Path
from random import sample
from socket import gethostname
from sys import _getframe, exit
from time import gmtime, sleep, strftime

# 3rd party
from dotenv import load_dotenv


# module target
from isogeo_pysdk import (
IsogeoSession,
__version__ as pysdk_version,
FeatureAttribute,
Metadata,
)


# #############################################################################
# ######## Globals #################
# ##################################


if Path("dev.env").exists():
load_dotenv("dev.env", override=True)

# host machine name - used as discriminator
hostname = gethostname()

# API access
METADATA_TEST_FIXTURE_UUID = environ.get("ISOGEO_FIXTURES_METADATA_COMPLETE")
WORKGROUP_TEST_FIXTURE_UUID = environ.get("ISOGEO_WORKGROUP_TEST_UUID")

# #############################################################################
# ########## Helpers ###############
# ##################################


def get_test_marker():
"""Returns the function name"""
return "TEST_PySDK - FeatureAttributes {}".format(_getframe(1).f_code.co_name)


# #############################################################################
# ########## Classes ###############
# ##################################


class TestFeatureAttributes(unittest.TestCase):
"""Test FeatureAttribute model of Isogeo API."""

# -- Standard methods --------------------------------------------------------
@classmethod
def setUpClass(cls):
"""Executed when module is loaded before any test."""
# checks
if not environ.get("ISOGEO_API_USER_CLIENT_ID") or not environ.get(
"ISOGEO_API_USER_CLIENT_SECRET"
):
logging.critical("No API credentials set as env variables.")
exit()
else:
pass

# ignore warnings related to the QA self-signed cert
if environ.get("ISOGEO_PLATFORM").lower() == "qa":
urllib3.disable_warnings()

# API connection
cls.isogeo = IsogeoSession(
client_id=environ.get("ISOGEO_API_USER_CLIENT_ID"),
client_secret=environ.get("ISOGEO_API_USER_CLIENT_SECRET"),
auto_refresh_url="{}/oauth/token".format(environ.get("ISOGEO_ID_URL")),
platform=environ.get("ISOGEO_PLATFORM", "qa"),
)
# getting a token
cls.isogeo.connect(
username=environ.get("ISOGEO_USER_NAME"),
password=environ.get("ISOGEO_USER_PASSWORD"),
)

# class vars and attributes
cls.li_fixtures_to_delete = []

md = Metadata(title=get_test_marker(), type="vectorDataset")
cls.metadata_fixture_created = cls.isogeo.metadata.create(
WORKGROUP_TEST_FIXTURE_UUID, metadata=md, check_exists=0
)
cls.metadata_fixture_existing = cls.isogeo.metadata.get(
metadata_id=METADATA_TEST_FIXTURE_UUID
)

def setUp(self):
"""Executed before each test."""
# tests stuff
self.discriminator = "{}_{}".format(
hostname, strftime("%Y-%m-%d_%H%M%S", gmtime())
)

def tearDown(self):
"""Executed after each test."""
sleep(0.5)

@classmethod
def tearDownClass(cls):
"""Executed after the last test."""
# clean created metadata
cls.isogeo.metadata.delete(cls.metadata_fixture_created._id)
# clean created licenses
if len(cls.li_fixtures_to_delete):
for i in cls.li_fixtures_to_delete:
cls.isogeo.metadata.featureAttributes.delete(featureAttribute=i)
# close sessions
cls.isogeo.close()

# -- TESTS ---------------------------------------------------------

# -- GET --
def test_featureAttributes_listing(self):
"""GET :resources/{metadata_uuid}/featureAttributes/}"""
# retrieve workgroup featureAttributes
md_featureAttributes = self.isogeo.metadata.attributes.listing(
self.metadata_fixture_existing
)
# parse and test object loader
for i in md_featureAttributes:
# load it
attribute = FeatureAttribute(**i)
# tests attributes structure
self.assertTrue(hasattr(attribute, "_id"))
self.assertTrue(hasattr(attribute, "alias"))
self.assertTrue(hasattr(attribute, "dataType"))
self.assertTrue(hasattr(attribute, "description"))
self.assertTrue(hasattr(attribute, "language"))
self.assertTrue(hasattr(attribute, "name"))
self.assertTrue(hasattr(attribute, "parent_resource"))
# tests attributes value
self.assertEqual(attribute._id, i.get("_id"))
self.assertEqual(attribute.alias, i.get("alias"))
self.assertEqual(attribute.dataType, i.get("dataType"))
self.assertEqual(attribute.description, i.get("description"))
self.assertEqual(attribute.name, i.get("name"))
self.assertEqual(attribute.parent_resource, i.get("parent_resource"))


# ##############################################################################
# ##### Stand alone program ########
# ##################################
if __name__ == "__main__":
unittest.main()

0 comments on commit dc60d19

Please sign in to comment.