Commit 77943a94 by Madhan Neethiraj

ATLAS-4077: updated Python client to support Python 2.7

parent cc333af6
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import logging import logging
from utils import TABLE_TYPE from utils import TABLE_TYPE
......
...@@ -20,7 +20,10 @@ ...@@ -20,7 +20,10 @@
import json import json
import logging import logging
from apache_atlas.model.entity import AtlasEntityWithExtInfo, EntityMutations from apache_atlas.model.enums import EntityOperation
from apache_atlas.model.instance import AtlasEntityWithExtInfo, EntityMutations, AtlasRelatedObjectId
from apache_atlas.utils import type_coerce
LOG = logging.getLogger('entity-example') LOG = logging.getLogger('entity-example')
...@@ -41,10 +44,10 @@ class EntityExample: ...@@ -41,10 +44,10 @@ class EntityExample:
def __init__(self, client): def __init__(self, client):
self.client = client self.client = client
self.db_entity = None self.entity_db = None
self.entity_table_us = None self.entity_table_us = None
self.entity_table_canada = None self.entity_table_canada = None
self.load_process = None self.entity_process = None
def create_entities(self): def create_entities(self):
self.__create_db() self.__create_db()
...@@ -58,132 +61,129 @@ class EntityExample: ...@@ -58,132 +61,129 @@ class EntityExample:
return None return None
def get_entity_by_guid(self, entity_guid): def get_entity_by_guid(self, guid):
entity_with_ext_info = self.client.entity.get_entity_by_guid(entity_guid) entity = self.client.entity.get_entity_by_guid(guid)
if entity_with_ext_info: LOG.info("Entity(guid=%s): typeName=%s, attr.name=%s", guid, entity.entity.typeName, entity.entity.attributes['name'])
LOG.info("Entity info is : %s", entity_with_ext_info)
def remove_entities(self): def remove_entities(self):
delete_entity_list = [self.load_process['guid'], self.entity_table_us['guid'], self.entity_table_canada['guid'], self.db_entity['guid']] entity_list = [ self.entity_process.guid, self.entity_table_us.guid, self.entity_table_canada.guid, self.entity_db.guid ]
response = self.client.entity.purge_entities_by_guids(delete_entity_list)
if not response:
LOG.info("There is no entity to delete!")
LOG.info("Deletion complete for DB entity: %s, US entity: %s, Canada entity: %s and Process entity: %s", self.client.entity.delete_entities_by_guids(entity_list)
self.db_entity['typeName'],
self.entity_table_us['typeName'],
self.entity_table_canada['typeName'],
self.load_process['typeName'])
def __create_db(self): response = self.client.entity.purge_entities_by_guids(entity_list)
if not self.db_entity:
with open('request_json/entity_create_db.json') as f:
entity_db = json.load(f)
self.db_entity = self.__create_db_helper(entity_db)
if self.db_entity: if response is not None:
LOG.info("Created database entity: %s", self.db_entity['typeName']) LOG.info("Purged entities")
else: else:
LOG.info("Database entity not created") LOG.info("Purge failed!")
def __create_db_helper(self, ext_info): def __create_db(self):
instance_entity = ext_info['entity'] if not self.entity_db:
entity = self.__create_entity(ext_info) with open('request_json/entity_create_db.json') as f:
entity = type_coerce(json.load(f), AtlasEntityWithExtInfo)
if entity and entity['guid']: self.entity_db = self.__create_db_helper(entity)
instance_entity['guid'] = entity['guid']
return instance_entity if self.entity_db:
LOG.info("Created database entity: guid=%s, attr.name=%s", self.entity_db.guid, self.entity_db.attributes['name'])
else:
LOG.info("Failed to create database entity")
def __create_us_table(self): def __create_us_table(self):
if not self.entity_table_us: if not self.entity_table_us:
with open('request_json/entity_create_table_us.json') as f: with open('request_json/entity_create_table_us.json') as f:
entity_table_us = json.load(f) entity = type_coerce(json.load(f), AtlasEntityWithExtInfo)
self.entity_table_us = self.__create_table_helper(entity_table_us)
self.entity_table_us = self.__create_table_helper(entity)
if self.entity_table_us: if self.entity_table_us:
LOG.info("Created table entity for US: %s", self.entity_table_us['typeName']) LOG.info("Created US table entity: guid=%s, attr.name=%s", self.entity_table_us.guid, self.entity_table_us.attributes['name'])
else: else:
LOG.info("Table entity for US not created") LOG.info("Failed to create US table entity")
def __create_canada_table(self): def __create_canada_table(self):
if not self.entity_table_canada: if not self.entity_table_canada:
with open('request_json/entity_create_table_canada.json') as f: with open('request_json/entity_create_table_canada.json') as f:
entity_table_canada = json.load(f) entity = type_coerce(json.load(f), AtlasEntityWithExtInfo)
self.entity_table_canada = self.__create_table_helper(entity_table_canada)
self.entity_table_canada = self.__create_table_helper(entity)
if self.entity_table_canada: if self.entity_table_canada:
LOG.info("Created table entity for Canada: %s", self.entity_table_canada['typeName']) LOG.info("Created Canada table entity: guid=%s, attr.name=%s", self.entity_table_canada.guid, self.entity_table_canada.attributes['name'])
else: else:
LOG.info("Table entity for Canada not created") LOG.info("Failed to create Canada table entity")
def __create_table_helper(self, ext_info): def __create_process(self):
instance_entity = ext_info['entity'] if not self.entity_process:
with open('request_json/entity_create_process.json') as f:
entity = type_coerce(json.load(f), AtlasEntityWithExtInfo)
if self.db_entity: self.entity_process = self.__create_process_helper(entity)
instance_entity['relationshipAttributes']['db']['guid'] = self.db_entity['guid']
instance_entity['relationshipAttributes']['db']['typeName'] = self.db_entity['typeName']
ext_info['entity'] = instance_entity if self.entity_process:
LOG.info("Created process entity: guid=%s, attr.name=%s", self.entity_process.guid, self.entity_process.attributes['name'])
else:
LOG.info("Failed to createa process entity")
entity = self.__create_entity(ext_info) def __create_db_helper(self, entity):
self.__create_entity(entity)
if entity and entity['guid']: return entity.entity
instance_entity['guid'] = entity['guid']
return instance_entity def __create_table_helper(self, entity):
table = entity.entity
def __create_process(self): if self.entity_db:
if not self.load_process: dbId = AtlasRelatedObjectId({ 'guid': self.entity_db.guid })
with open('request_json/entity_create_process.json') as f:
entity_process = json.load(f)
self.load_process = self.__create_process_helper(entity_process)
if self.load_process: LOG.info("setting: table(%s).db=%s", table.guid, dbId)
LOG.info("Created process Entity: %s", self.load_process['typeName'])
else:
LOG.info("Process Entity not created")
def __create_process_helper(self, ext_info): table.relationshipAttributes['db'] = dbId
instance_entity = ext_info['entity']
if self.entity_table_us: self.__create_entity(entity)
input_list = []
input_data = {'guid': self.entity_table_us['guid'], return table
'typeName': self.entity_table_us['typeName']
}
input_list.append(input_data) def __create_process_helper(self, entity):
process = entity.entity
instance_entity['relationshipAttributes']['inputs'] = input_list process.relationshipAttributes = {}
if self.entity_table_us:
process.relationshipAttributes['inputs'] = [ AtlasRelatedObjectId({ 'guid': self.entity_table_us.guid }) ]
if self.entity_table_canada: if self.entity_table_canada:
output_list = [] process.relationshipAttributes['outputs'] = [ AtlasRelatedObjectId({'guid': self.entity_table_canada.guid }) ]
output_data = {'guid': self.entity_table_canada['guid'],
'typeName': self.entity_table_canada['typeName']
}
output_list.append(output_data) return self.__create_entity(entity)
instance_entity['relationshipAttributes']['outputs'] = output_list def __create_entity(self, entity):
try:
response = self.client.entity.create_entity(entity)
ext_info['entity'] = instance_entity guid = None
return self.__create_entity(ext_info) if response and response.mutatedEntities:
if EntityOperation.CREATE.name in response.mutatedEntities:
header_list = response.mutatedEntities[EntityOperation.CREATE.name]
elif EntityOperation.UPDATE.name in response.mutatedEntities:
header_list = response.mutatedEntities[EntityOperation.UPDATE.name]
def __create_entity(self, ext_info): if header_list and len(header_list) > 0:
try: guid = header_list[0].guid
entity = self.client.entity.create_entity(ext_info) elif response and response.guidAssignments:
create_enum = EntityMutations.entity_operation_enum.CREATE.name if entity.entity is not None and entity.entity.guid is not None:
in_guid = entity.entity.guid
else:
in_guid = None
if entity and entity.mutatedEntities and entity.mutatedEntities[create_enum]: if in_guid and response.guidAssignments[in_guid]:
header_list = entity.mutatedEntities[create_enum] guid = response.guidAssignments[in_guid]
if len(header_list) > 0: if guid:
return header_list[0] entity.entity.guid = guid
except Exception as e: except Exception as e:
LOG.exception("failed to create entity %s", ext_info['entity']) LOG.exception("failed to create entity %s. error=%s", entity, e)
return None return entity.entity if entity and entity.entity else None
\ No newline at end of file
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
# limitations under the License. # limitations under the License.
import logging import logging
from apache_atlas.model.glossary import AtlasGlossary, AtlasGlossaryCategory, AtlasGlossaryTerm, AtlasGlossaryHeader from apache_atlas.model.glossary import AtlasGlossary, AtlasGlossaryCategory, AtlasGlossaryTerm, AtlasGlossaryHeader
LOG = logging.getLogger('glossary-example') LOG = logging.getLogger('glossary-example')
...@@ -33,7 +34,7 @@ class GlossaryExample: ...@@ -33,7 +34,7 @@ class GlossaryExample:
self.emp_company_category = None self.emp_company_category = None
def create_glossary(self): def create_glossary(self):
glossary = AtlasGlossary(None, None, GlossaryExample.glossaryName, "This is a test Glossary") glossary = AtlasGlossary({ 'name': GlossaryExample.glossaryName, 'shortDescription': 'This is a test Glossary' })
self.emp_glossary = self.client.glossary.create_glossary(glossary) self.emp_glossary = self.client.glossary.create_glossary(glossary)
LOG.info("Created glossary with name: %s and guid: %s", self.emp_glossary.name, self.emp_glossary.guid) LOG.info("Created glossary with name: %s and guid: %s", self.emp_glossary.name, self.emp_glossary.guid)
...@@ -47,16 +48,18 @@ class GlossaryExample: ...@@ -47,16 +48,18 @@ class GlossaryExample:
LOG.info("Glossary extended info: %s; name: %s; language: %s", ext_info.guid, ext_info.name, ext_info.language) LOG.info("Glossary extended info: %s; name: %s; language: %s", ext_info.guid, ext_info.name, ext_info.language)
def create_glossary_term(self): def create_glossary_term(self):
header = AtlasGlossaryHeader(self.emp_glossary.guid, None, self.emp_glossary.name) header = AtlasGlossaryHeader({ 'glossaryGuid': self.emp_glossary.guid, 'displayText': self.emp_glossary.name })
term = AtlasGlossaryTerm(None, None, "EmpSalaryTerm", None, None, None, None, None, None, None, header) term = AtlasGlossaryTerm({ 'name': 'EmpSalaryTerm', 'anchor': header })
self.emp_salary_term = self.client.glossary.create_glossary_term(term) self.emp_salary_term = self.client.glossary.create_glossary_term(term)
if self.emp_salary_term: if self.emp_salary_term:
LOG.info("Created Term for Employee Salary: %s with guid: %s", self.emp_salary_term.name, self.emp_salary_term.guid) LOG.info("Created Term for Employee Salary: %s with guid: %s", self.emp_salary_term.name, self.emp_salary_term.guid)
def create_glossary_category(self): def create_glossary_category(self):
header = AtlasGlossaryHeader(self.emp_glossary.guid, None, self.emp_glossary.name) header = AtlasGlossaryHeader({ 'glossaryGuid': self.emp_glossary.guid, 'displayText': self.emp_glossary.name })
category = AtlasGlossaryCategory(None, None, "EmpSalaryCategory", None, None, None, None, header) category = AtlasGlossaryCategory({ 'name': 'EmpSalaryCategory', 'anchor': header })
self.emp_company_category = self.client.glossary.create_glossary_category(category) self.emp_company_category = self.client.glossary.create_glossary_category(category)
if self.emp_company_category: if self.emp_company_category:
......
...@@ -16,20 +16,20 @@ ...@@ -16,20 +16,20 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import logging import logging
from apache_atlas.model.lineage import AtlasLineageInfo from apache_atlas.model.enums import LineageDirection
LOG = logging.getLogger('lineage-example') LOG = logging.getLogger('lineage-example')
class LineageExample: class LineageExample:
def __init__(self, client): def __init__(self, client):
self.client = client self.client = client
def lineage(self, guid): def lineage(self, guid):
direction = AtlasLineageInfo.lineageDirection_enum.BOTH.name direction = LineageDirection.BOTH.name
lineage_info = self.client.lineage.get_lineage_info(guid, direction, 0) lineage_info = self.client.lineage.get_lineage_info(guid, direction, 0)
if not lineage_info: if not lineage_info:
...@@ -40,7 +40,7 @@ class LineageExample: ...@@ -40,7 +40,7 @@ class LineageExample:
guid_entity_map = lineage_info.guidEntityMap guid_entity_map = lineage_info.guidEntityMap
for relation in relations: for relation in relations:
from_entity = guid_entity_map[relation['fromEntityId']] from_entity = guid_entity_map[relation.fromEntityId]
to_entity = guid_entity_map[relation['toEntityId']] to_entity = guid_entity_map[relation.toEntityId]
LOG.info("%s (%s) -> %s (%s)", from_entity['displayText'], from_entity['typeName'], to_entity['displayText'], to_entity['typeName']) LOG.info("%s (%s) -> %s (%s)", from_entity.displayText, from_entity.typeName, to_entity.displayText, to_entity.typeName)
\ No newline at end of file \ No newline at end of file
{ {
"entity": { "entity": {
"typeName": "sample_db_type", "guid": "-1",
"typeName": "sample_db",
"attributes": { "attributes": {
"owner": "user", "name": "employee_db",
"createTime": 1000, "qualifiedName": "employee_db@cl1",
"@cl1": "employeeCluster",
"qualifiedName": "employee_db_entity@cl1",
"name": "employee_db_entity",
"description": "employee database", "description": "employee database",
"locationUri": "/tmp" "owner": "user",
}, "clusterName": "cl1",
"guid": "-222736766326565", "locationUri": "/hive/database/employee_db",
"isIncomplete": false, "createTime": 1607476058882
"provenanceType": 0, }
"version": 0,
"proxy": false
} }
} }
{ {
"entity": { "entity": {
"typeName": "sample_process_type", "typeName": "sample_process",
"attributes": { "attributes": {
"queryGraph": "graph", "name": "employee_process",
"qualifiedName": "employee_process_entity@cl1",
"name": "employee_process_entity",
"queryText": "create table as select ",
"description": "hive query for monthly avg salary", "description": "hive query for monthly avg salary",
"startTime": 1596855233685, "qualifiedName": "employee_process@cl1",
"queryPlan": "plan",
"operationType": "testOperation",
"endTime": 1596855243685,
"userName": "user ETL", "userName": "user ETL",
"queryId": "id" "startTime": 1607476549507,
"endTime": 1607476552529,
"queryText": "create table as select ",
"queryId": "<query-id>"
}, },
"guid": "-222736766326574",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": { "relationshipAttributes": {
"outputs": [{ "inputs": [ { "typeName": "sample_table", "uniqueAttributes": { "qualifiedName": "employee_db.employees_us@cl1" } } ],
"guid": "b0619fb9-b025-4348-8b8a-79e8faa0e789", "outputs": [ { "typeName": "sample_table", "uniqueAttributes": { "qualifiedName": "employee_db.employees_canada@cl1" } } ]
"typeName": "sample_table_type" }
}],
"inputs": [{
"guid": "b49bb0fe-4714-4122-901a-9ac433a89ccd",
"typeName": "sample_table_type"
}]
},
"classifications": [{
"typeName": "classification",
"entityStatus": "ACTIVE"
}],
"proxy": false
} }
} }
{ {
"referredEntities": { "entity": {
"-222736766326566": { "guid": "-1",
"typeName": "sample_column_type", "typeName": "sample_table",
"attributes": { "attributes": {
"qualifiedName": "time_id@cl1", "name": "employees_canada",
"dataType": "int", "description": "Canada employees",
"name": "time_id", "qualifiedName": "employee_db.employees_canada@cl1",
"comment": "time id" "tableType": "Managed",
"serde1": { "typeName": "sample_serdeType", "attributes": { "name": "serde1", "serde": "serde1" } },
"serde2": { "typeName": "sample_serdeType", "attributes": { "name": "serde2", "serde": "serde2" } }
}, },
"guid": "-222736766326566",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": { "relationshipAttributes": {
"table": { "db": { "typeName": "sample_db", "uniqueAttributes": { "qualifiedName": "employee_db@cl1" } },
"guid": "-222736766326569", "columns": [
"typeName": "sample_table_type" { "guid": "-2" },
{ "guid": "-3" },
{ "guid": "-4" }
]
} }
}, },
"classifications": [],
"proxy": false "referredEntities": {
}, "-2": {
"-222736766326567": { "guid": "-2",
"typeName": "sample_column_type", "typeName": "sample_column",
"attributes": { "attributes": {
"qualifiedName": "customer_id@cl1", "table": { "guid": "-1" },
"name": "time_id",
"dataType": "int", "dataType": "int",
"name": "customer_id", "comment": "time id",
"comment": "customer id" "qualifiedName": "employee_db.employees_canada.time_id@cl1"
},
"guid": "-222736766326567",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326569",
"typeName": "sample_table_type"
}
},
"classifications": [{
"typeName": "sample_pii_Tag",
"entityStatus": "ACTIVE"
}],
"proxy": false
},
"-222736766326568": {
"typeName": "sample_column_type",
"attributes": {
"qualifiedName": "company_id@cl1",
"dataType": "double",
"name": "company_id",
"comment": "company id"
},
"guid": "-222736766326568",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326569",
"typeName": "sample_table_type"
}
},
"classifications": [{
"typeName": "sample_finance_Tag",
"entityStatus": "ACTIVE"
}],
"proxy": false
} }
}, },
"entity": { "-3": {
"typeName": "sample_table_type", "guid": "-3",
"typeName": "sample_column",
"attributes": { "attributes": {
"serde2": { "table": { "guid": "-1" },
"typeName": "serdeType", "name": "customer_id",
"attributes": { "dataType": "int",
"serde": "serde2", "comment": "customer id",
"name": "serde2" "qualifiedName": "employee_db.employees_canada.customer_id@cl1"
} }
}, },
"tableType": "Managed", "-4": {
"serde1": { "guid": "-4",
"typeName": "serdeType", "typeName": "sample_column",
"attributes": { "attributes": {
"serde": "serde1", "table": { "guid": "-1" },
"name": "serde1" "name": "company_id",
"dataType": "double",
"comment": "company id",
"qualifiedName": "employee_db.employees_canada.company_id@cl1"
} }
},
"lastAccessTime": "2014-07-11T08:00:00.000Z",
"level": 2,
"qualifiedName": "employee_table_entity_CANADA@cl1",
"name": "employee_table_entity_CANADA",
"description": "emp table",
"compressed": false
},
"guid": "-222736766326569",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"columns": [{
"guid": "-222736766326566",
"typeName": "sample_column_type"
}, {
"guid": "-222736766326567",
"typeName": "sample_column_type"
}, {
"guid": "-222736766326568",
"typeName": "sample_column_type"
}],
"db": {
"guid": "c1e152c4-e40a-4bc9-a8a1-3c09d8d85f17",
"typeName": "sample_db_type"
} }
},
"classifications": [{
"typeName": "Metric",
"entityStatus": "ACTIVE"
}],
"proxy": false
} }
} }
{ {
"referredEntities": { "entity": {
"-222736766326570": { "guid": "-1",
"typeName": "sample_column_type", "typeName": "sample_table",
"attributes": { "attributes": {
"qualifiedName": "time_id@cl1", "name": "employees_us",
"dataType": "int", "description": "US employees",
"name": "time_id", "qualifiedName": "employee_db.employees_us@cl1",
"comment": "time id" "tableType": "Managed",
"serde1": { "typeName": "sample_serdeType", "attributes": { "name": "serde1", "serde": "serde1" } },
"serde2": { "typeName": "sample_serdeType", "attributes": { "name": "serde2", "serde": "serde2" } }
}, },
"guid": "-222736766326570",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": { "relationshipAttributes": {
"table": { "db": { "typeName": "sample_db", "uniqueAttributes": { "qualifiedName": "employee_db@cl1" } },
"guid": "-222736766326573", "columns": [
"typeName": "sample_table_type" { "guid": "-2" },
{ "guid": "-3" },
{ "guid": "-4" }
]
} }
}, },
"classifications": [],
"proxy": false "referredEntities": {
}, "-2": {
"-222736766326571": { "guid": "-2",
"typeName": "sample_column_type", "typeName": "sample_column",
"attributes": { "attributes": {
"qualifiedName": "customer_id@cl1", "name": "time_id",
"dataType": "int", "dataType": "int",
"name": "customer_id", "comment": "time id",
"comment": "customer id" "qualifiedName": "employee_db.employees_us.time_id@cl1",
}, "table": { "guid": "-1" }
"guid": "-222736766326571",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326573",
"typeName": "sample_table_type"
}
},
"classifications": [{
"typeName": "sample_pii_Tag",
"entityStatus": "ACTIVE"
}],
"proxy": false
},
"-222736766326572": {
"typeName": "sample_column_type",
"attributes": {
"qualifiedName": "company_id@cl1",
"dataType": "double",
"name": "company_id",
"comment": "company id"
},
"guid": "-222736766326572",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326573",
"typeName": "sample_table_type"
}
},
"classifications": [{
"typeName": "sample_finance_Tag",
"entityStatus": "ACTIVE"
}],
"proxy": false
} }
}, },
"entity": { "-3": {
"typeName": "sample_table_type", "guid": "-3",
"typeName": "sample_column",
"attributes": { "attributes": {
"serde2": { "name": "customer_id",
"typeName": "serdeType", "dataType": "int",
"attributes": { "comment": "customer id",
"serde": "serde2", "qualifiedName": "employee_db.employees_us.customer_id@cl1",
"name": "serde2" "table": { "guid": "-1" }
} }
}, },
"tableType": "Managed", "-4": {
"serde1": { "guid": "-4",
"typeName": "serdeType", "typeName": "sample_column",
"attributes": { "attributes": {
"serde": "serde1", "name": "company_id",
"name": "serde1" "dataType": "double",
"comment": "company id",
"qualifiedName": "employee_db.employees_us.company_id@cl1",
"table": { "guid": "-1" }
} }
},
"lastAccessTime": "2014-07-11T08:00:00.000Z",
"level": 2,
"qualifiedName": "employee_table_entity_US@cl1",
"name": "employee_table_entity_US",
"description": "emp table",
"compressed": false
},
"guid": "-222736766326573",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"columns": [{
"guid": "-222736766326570",
"typeName": "sample_column_type"
}, {
"guid": "-222736766326571",
"typeName": "sample_column_type"
}, {
"guid": "-222736766326572",
"typeName": "sample_column_type"
}],
"db": {
"guid": "c1e152c4-e40a-4bc9-a8a1-3c09d8d85f17",
"typeName": "sample_db_type"
} }
},
"classifications": [{
"typeName": "Metric",
"entityStatus": "ACTIVE"
}],
"proxy": false
} }
} }
{ {
"enumDefs": [ "enumDefs": [
{ {
"category": "ENUM", "name": "sample_tableType",
"name": "tableType", "description": "sample_tableType",
"description": "tableType", "typeVersion": "1.0",
"elementDefs": [ "elementDefs": [
{ { "value": "MANAGED", "ordinal": 1 },
"value": "MANAGED", { "value": "EXTERNAL", "ordinal": 2 }
"ordinal": 1
},
{
"value": "EXTERNAL",
"ordinal": 2
}
] ]
} }
], ],
"structDefs": [ "structDefs": [
{ {
"category": "STRUCT", "name": "sample_serdeType",
"name": "serdeType",
"typeVersion": "1.0", "typeVersion": "1.0",
"attributeDefs": [ "attributeDefs": [
{ { "name": "name", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true },
"name": "name", { "name": "serde", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true }
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": false,
"isUnique": false,
"isIndexable": true
},
{
"name": "serde",
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": false,
"isUnique": false,
"isIndexable": true
}
] ]
} }
], ],
"classificationDefs": [ "classificationDefs": [
{ {
"category": "CLASSIFICATION", "name": "sample_pii",
"name": "classification",
"typeVersion": "1.0",
"attributeDefs": [
{
"name": "tag",
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": false,
"isUnique": false,
"isIndexable": true
}
]
},
{
"category": "CLASSIFICATION",
"name": "sample_pii_Tag",
"typeVersion": "1.0" "typeVersion": "1.0"
}, },
{ {
"category": "CLASSIFICATION", "name": "sample_finance",
"name": "sample_finance_Tag",
"typeVersion": "1.0" "typeVersion": "1.0"
}, },
{ {
"category": "CLASSIFICATION", "name": "sample_metric",
"name": "Metric",
"typeVersion": "1.0" "typeVersion": "1.0"
} }
], ],
"entityDefs": [ "entityDefs": [
{ {
"category": "ENTITY", "name": "sample_db",
"name": "sample_db_type", "superTypes": [ "DataSet" ],
"typeVersion": "1.0", "typeVersion": "1.0",
"attributeDefs": [ "attributeDefs": [
{ { "name": "locationUri", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true },
"name": "locationUri", { "name": "createTime", "typeName": "date", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true }
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "createTime",
"typeName": "long",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "randomTable",
"typeName": "array<sample_table_type>",
"cardinality": "SET",
"isOptional": true,
"isUnique": false,
"isIndexable": false
}
],
"superTypes": [
"DataSet"
] ]
}, },
{ {
"category": "ENTITY", "name": "sample_table",
"name": "sample_table_type",
"typeVersion": "1.0", "typeVersion": "1.0",
"superTypes": [ "DataSet" ],
"attributeDefs": [ "attributeDefs": [
{ { "name": "createTime", "typeName": "date", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true },
"name": "createTime", { "name": "tableType", "typeName": "sample_tableType", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true },
"typeName": "long", { "name": "temporary", "typeName": "boolean", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": false },
"cardinality": "SINGLE", { "name": "serde1", "typeName": "sample_serdeType", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": false },
"isOptional": true, { "name": "serde2", "typeName": "sample_serdeType", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": false }
"isUnique": false,
"isIndexable": false
},
{
"name": "lastAccessTime",
"typeName": "date",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "temporary",
"typeName": "boolean",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "db",
"typeName": "sample_db_type",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "columns",
"typeName": "array<sample_column_type>",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "tableType",
"typeName": "tableType",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "serde1",
"typeName": "serdeType",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "serde2",
"typeName": "serdeType",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
}
],
"superTypes": [
"DataSet"
] ]
}, },
{ {
"category": "ENTITY", "name": "sample_column",
"name": "sample_column_type",
"typeVersion": "1.0", "typeVersion": "1.0",
"superTypes": [ "DataSet" ],
"attributeDefs": [ "attributeDefs": [
{ { "name": "dataType", "typeName": "string", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true },
"name": "dataType", { "name": "comment", "typeName": "string", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true }
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "comment",
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
}
],
"superTypes": [
"DataSet"
] ]
}, },
{ {
"category": "ENTITY", "name": "sample_process",
"name": "sample_process_type",
"typeVersion": "1.0", "typeVersion": "1.0",
"superTypes": [ "Process" ],
"attributeDefs": [ "attributeDefs": [
{ { "name": "userName", "typeName": "string", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true },
"name": "userName", { "name": "startTime", "typeName": "long", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true },
"typeName": "string", { "name": "endTime", "typeName": "long", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true },
"cardinality": "SINGLE", { "name": "queryText", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true },
"isOptional": true, { "name": "queryId", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true }
"isUnique": false,
"isIndexable": false
},
{
"name": "startTime",
"typeName": "long",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "endTime",
"typeName": "long",
"cardinality": "SINGLE",
"isOptional": true,
"isUnique": false,
"isIndexable": false
},
{
"name": "queryText",
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": false,
"isUnique": false,
"isIndexable": true
},
{
"name": "queryPlan",
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": false,
"isUnique": false,
"isIndexable": true
},
{
"name": "queryId",
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": false,
"isUnique": false,
"isIndexable": true
},
{
"name": "queryGraph",
"typeName": "string",
"cardinality": "SINGLE",
"isOptional": false,
"isUnique": false,
"isIndexable": true
}
],
"superTypes": [
"Process"
] ]
} }
], ],
"relationshipDefs": [ "relationshipDefs": [
{ {
"category": "RELATIONSHIP", "name": "sample_db_tables",
"name": "sample_Table_DB", "description": "Tables of a db",
"description": "sample_Table_DB",
"typeVersion": "1.0", "typeVersion": "1.0",
"relationshipCategory": "AGGREGATION", "relationshipCategory": "AGGREGATION",
"propagateTags": "NONE", "propagateTags": "NONE",
"endDef1": { "endDef1": { "name": "db", "type": "sample_table", "cardinality": "SINGLE", "isContainer": false, "isLegacyAttribute": false },
"type": "sample_table_type", "endDef2": { "name": "tables", "type": "sample_db", "cardinality": "SET", "isContainer": true, "isLegacyAttribute": false }
"name": "db",
"cardinality": "SINGLE",
"isContainer": false,
"isLegacyAttribute": false
},
"endDef2": {
"type": "sample_db_type",
"name": "tables",
"cardinality": "SET",
"isContainer": true,
"isLegacyAttribute": false
}
}, },
{ {
"category": "RELATIONSHIP", "name": "sample_table_columns",
"name": "sample_Table_Columns", "description": "Columns of a table",
"description": "sample_Table_Columns",
"typeVersion": "1.0", "typeVersion": "1.0",
"relationshipCategory": "COMPOSITION", "relationshipCategory": "COMPOSITION",
"propagateTags": "NONE", "propagateTags": "NONE",
"endDef1": { "endDef1": { "name": "table", "type": "sample_column", "cardinality": "SINGLE", "isContainer": false, "isLegacyAttribute": false },
"type": "sample_table_type", "endDef2": { "name": "columns", "type": "sample_table", "cardinality": "SET", "isContainer": true, "isLegacyAttribute": false }
"name": "columns",
"cardinality": "SET",
"isContainer": true,
"isLegacyAttribute": false
},
"endDef2": {
"type": "sample_column_type",
"name": "table",
"cardinality": "SINGLE",
"isContainer": false,
"isLegacyAttribute": false
}
} }
], ],
"businessMetadataDefs": [ "businessMetadataDefs": [
{ {
"category": "BUSINESS_METADATA", "name": "sample_bm",
"name": "bmWithAllTypes", "description": "Sample business metadata",
"description": "description",
"typeVersion": "1.0", "typeVersion": "1.0",
"attributeDefs": [ "attributeDefs": [
{ {
"name": "attr1", "name": "attr1",
"typeName": "boolean", "typeName": "boolean",
"description": "Boolean attribute",
"cardinality": "SINGLE", "cardinality": "SINGLE",
"isOptional": true, "isOptional": true,
"isIndexable": false,
"includeInNotification": false,
"defaultValue": "",
"description": "description",
"searchWeight": 0,
"options": { "options": {
"applicableEntityTypes": "[\"sample_db_type\",\"sample_table_type\"]", "applicableEntityTypes": "[ \"sample_db\", \"sample_table\" ]",
"maxStrLength": "20" "maxStrLength": 50
} }
}, },
{ {
"name": "attr2", "name": "attr2",
"typeName": "byte", "typeName": "byte",
"description": "Byte attribute",
"cardinality": "SINGLE", "cardinality": "SINGLE",
"isOptional": true, "isOptional": true,
"isUnique": false, "isUnique": false,
"isIndexable": false, "isIndexable": true,
"includeInNotification": false,
"defaultValue": "",
"description": "description",
"searchWeight": 0,
"options": { "options": {
"applicableEntityTypes": "[\"sample_db_type\",\"sample_table_type\"]", "applicableEntityTypes": "[ \"sample_db\", \"sample_table\" ]",
"maxStrLength": "20" "maxStrLength": 50
} }
}, },
{ {
"name": "attr8", "name": "attr3",
"typeName": "string", "typeName": "string",
"description": "String attribute",
"cardinality": "SINGLE", "cardinality": "SINGLE",
"isOptional": true, "isOptional": true,
"isUnique": false, "isUnique": false,
"isIndexable": false, "isIndexable": true,
"includeInNotification": false,
"defaultValue": "",
"description": "description",
"searchWeight": 0, "searchWeight": 0,
"options": { "options": {
"applicableEntityTypes": "[\"sample_db_type\",\"sample_table_type\"]", "applicableEntityTypes": "[ \"sample_db\", \"sample_table\" ]",
"maxStrLength": "20" "maxStrLength": 50
} }
} }
] ]
}, },
{ {
"category": "BUSINESS_METADATA", "name": "sample_bm_mv",
"name": "bmWithAllTypesMV", "description": "Sample business metadata with multi-value attributes",
"description": "description",
"typeVersion": "1.0", "typeVersion": "1.0",
"attributeDefs": [ "attributeDefs": [
{ {
"name": "attr11", "name": "mv_attr1",
"typeName": "array<boolean>", "typeName": "array<boolean>",
"description": "Array of booleans",
"cardinality": "SINGLE", "cardinality": "SINGLE",
"isOptional": true, "isOptional": true,
"isUnique": false,
"isIndexable": false,
"defaultValue": "",
"description": "description",
"searchWeight": 0,
"options": { "options": {
"applicableEntityTypes": "[\"sample_db_type\",\"sample_table_type\"]", "applicableEntityTypes": "[\"sample_db\",\"sample_table\"]",
"maxStrLength": "20" "maxStrLength": 50
} }
}, },
{ {
"name": "attr18", "name": "mv_attr2",
"typeName": "array<string>", "typeName": "array<string>",
"description": "Array of strings",
"cardinality": "SINGLE", "cardinality": "SINGLE",
"isOptional": true, "isOptional": true,
"isUnique": false,
"isIndexable": false,
"defaultValue": "",
"description": "description",
"searchWeight": 0,
"options": { "options": {
"applicableEntityTypes": "[\"sample_db_type\",\"sample_table_type\"]", "applicableEntityTypes": "[ \"sample_db\", \"sample_table\" ]",
"maxStrLength": "20" "maxStrLength": 50
} }
} }
] ]
......
...@@ -16,17 +16,18 @@ ...@@ -16,17 +16,18 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import logging
from apache_atlas.base_client import AtlasClient import logging
import getpass
from apache_atlas.client.base_client import AtlasClient
from typedef_example import TypeDefExample from typedef_example import TypeDefExample
from entity_example import EntityExample from entity_example import EntityExample
from lineage_example import LineageExample from lineage_example import LineageExample
from glossary_example import GlossaryExample from glossary_example import GlossaryExample
from discovery_example import DiscoveryExample from discovery_example import DiscoveryExample
from utils import METRIC_CLASSIFICATION, NAME from utils import METRIC_CLASSIFICATION, NAME
import getpass
LOG = logging.getLogger('sample-example') LOG = logging.getLogger('sample-example')
...@@ -36,70 +37,62 @@ class SampleApp: ...@@ -36,70 +37,62 @@ class SampleApp:
self.created_entity = None self.created_entity = None
def main(self): def main(self):
url = input("Enter Atlas URL: ") # Python3
username = input("Enter username: ") global input
password = getpass.getpass('Enter password: ') try: input = raw_input
client = AtlasClient(url, username, password) except NameError: pass
# Typedef examples url = input('Enter Atlas URL: ')
LOG.info("\n") username = input('Enter username: ')
LOG.info("---------- Creating Sample Types -----------") password = getpass.getpass('Enter password: ')
typedef = TypeDefExample(client)
typedef.create_type_def()
typedef.print_typedefs()
# Entity example client = AtlasClient(url, (username, password))
LOG.info("\n")
LOG.info("---------- Creating Sample Entities -----------")
entity = EntityExample(client)
entity.create_entities()
self.created_entity = entity.get_table_entity() self.__entity_example(client)
if self.created_entity and self.created_entity['guid']: self.__typedef_example(client)
entity.get_entity_by_guid(self.created_entity['guid'])
# Lineage Examples
LOG.info("\n")
LOG.info("---------- Lineage example -----------")
self.__lineage_example(client) self.__lineage_example(client)
# Discovery Example
LOG.info("\n")
LOG.info("---------- Search example -----------")
self.__discovery_example(client) self.__discovery_example(client)
# Glossary Examples
LOG.info("\n")
LOG.info("---------- Glossary Example -----------")
self.__glossary_example(client) self.__glossary_example(client)
LOG.info("\n") self.__entity_cleanup()
LOG.info("---------- Deleting Entities -----------")
entity.remove_entities()
def __glossary_example(self, client):
glossary = GlossaryExample(client)
glossary_obj = glossary.create_glossary()
if not glossary_obj: def __typedef_example(self, client):
LOG.info("Create glossary first") LOG.info("\n---------- Creating Sample Types -----------")
return
glossary.create_glossary_term() typedefExample = TypeDefExample(client)
glossary.get_glossary_detail()
glossary.create_glossary_category() typedefExample.create_type_def()
glossary.delete_glossary()
def __entity_example(self, client):
LOG.info("\n---------- Creating Sample Entities -----------")
self.entityExample = EntityExample(client)
self.entityExample.create_entities()
self.created_entity = self.entityExample.get_table_entity()
if self.created_entity and self.created_entity.guid:
self.entityExample.get_entity_by_guid(self.created_entity.guid)
def __lineage_example(self, client): def __lineage_example(self, client):
LOG.info("\n---------- Lineage example -----------")
lineage = LineageExample(client) lineage = LineageExample(client)
if self.created_entity: if self.created_entity:
lineage.lineage(self.created_entity['guid']) lineage.lineage(self.created_entity.guid)
else: else:
LOG.info("Create entity first to get lineage info") LOG.info("Create entity first to get lineage info")
def __discovery_example(self, client): def __discovery_example(self, client):
LOG.info("\n---------- Search example -----------")
discovery = DiscoveryExample(client) discovery = DiscoveryExample(client)
discovery.dsl_search() discovery.dsl_search()
...@@ -108,9 +101,29 @@ class SampleApp: ...@@ -108,9 +101,29 @@ class SampleApp:
LOG.info("Create entity first to get search info") LOG.info("Create entity first to get search info")
return return
discovery.quick_search(self.created_entity['typeName']) discovery.quick_search(self.created_entity.typeName)
discovery.basic_search(self.created_entity.typeName, METRIC_CLASSIFICATION, self.created_entity.attributes[NAME])
def __glossary_example(self, client):
LOG.info("\n---------- Glossary Example -----------")
glossary = GlossaryExample(client)
glossary_obj = glossary.create_glossary()
if not glossary_obj:
LOG.info("Create glossary first")
return
glossary.create_glossary_term()
glossary.get_glossary_detail()
glossary.create_glossary_category()
glossary.delete_glossary()
def __entity_cleanup(self):
LOG.info("\n---------- Deleting Entities -----------")
discovery.basic_search(self.created_entity['typeName'], METRIC_CLASSIFICATION, self.created_entity['attributes'][NAME]) self.entityExample.remove_entities()
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -17,26 +17,28 @@ ...@@ -17,26 +17,28 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import json
import logging import logging
import utils import utils
from apache_atlas.utils import type_coerce
from apache_atlas.model.discovery import SearchFilter from apache_atlas.model.discovery import SearchFilter
from apache_atlas.model.typedef import AtlasTypesDef from apache_atlas.model.typedef import AtlasTypesDef
import json
LOG = logging.getLogger('sample-example') LOG = logging.getLogger('sample-example')
class TypeDefExample: class TypeDefExample:
SAMPLE_APP_TYPES = { SAMPLE_APP_TYPES = [
utils.PROCESS_TYPE,
utils.COLUMN_TYPE,
utils.TABLE_TYPE,
utils.DATABASE_TYPE, utils.DATABASE_TYPE,
utils.TABLE_TYPE,
utils.COLUMN_TYPE,
utils.PROCESS_TYPE,
utils.PII_TAG, utils.PII_TAG,
utils.CLASSIFICATION,
utils.FINANCE_TAG, utils.FINANCE_TAG,
utils.METRIC_CLASSIFICATION} utils.METRIC_CLASSIFICATION
]
def __init__(self, client): def __init__(self, client):
self.typesDef = None self.typesDef = None
...@@ -46,10 +48,10 @@ class TypeDefExample: ...@@ -46,10 +48,10 @@ class TypeDefExample:
try: try:
if not self.typesDef: if not self.typesDef:
with open('request_json/typedef_create.json') as f: with open('request_json/typedef_create.json') as f:
typedef = json.load(f) typedef = type_coerce(json.load(f), AtlasTypesDef)
self.typesDef = self.__create(typedef) self.typesDef = self.__create(typedef)
except Exception as e: except Exception as e:
LOG.exception("Error in creating typeDef.") LOG.exception("Error in creating typeDef", exc_info=e)
def print_typedefs(self): def print_typedefs(self):
for type_name in TypeDefExample.SAMPLE_APP_TYPES: for type_name in TypeDefExample.SAMPLE_APP_TYPES:
...@@ -63,8 +65,7 @@ class TypeDefExample: ...@@ -63,8 +65,7 @@ class TypeDefExample:
def remove_typedefs(self): def remove_typedefs(self):
if not self.typesDef: if not self.typesDef:
LOG.info("There is no typeDef to delete.") LOG.info("There is no typeDef to delete.")
return else:
for type_name in TypeDefExample.SAMPLE_APP_TYPES: for type_name in TypeDefExample.SAMPLE_APP_TYPES:
self.client.typedef.delete_type_by_name(type_name) self.client.typedef.delete_type_by_name(type_name)
...@@ -73,42 +74,49 @@ class TypeDefExample: ...@@ -73,42 +74,49 @@ class TypeDefExample:
LOG.info("Deleted typeDef successfully!") LOG.info("Deleted typeDef successfully!")
def __create(self, type_def): def __create(self, type_def):
types_to_create = AtlasTypesDef().__dict__ types_to_create = AtlasTypesDef()
for enum_def in type_def['enumDefs']: types_to_create.enumDefs = []
if self.client.typedef.type_with_name_exists(enum_def['name']): types_to_create.structDefs = []
LOG.info("Type with name %s already exists. Skipping.", enum_def['name']) types_to_create.classificationDefs = []
types_to_create.entityDefs = []
types_to_create.relationshipDefs = []
types_to_create.businessMetadataDefs = []
for enum_def in type_def.enumDefs:
if self.client.typedef.type_with_name_exists(enum_def.name):
LOG.info("Type with name %s already exists. Skipping.", enum_def.name)
else: else:
types_to_create['enumDefs'].append(enum_def) types_to_create.enumDefs.append(enum_def)
for struct_def in type_def['structDefs']: for struct_def in type_def.structDefs:
if self.client.typedef.type_with_name_exists(struct_def['name']): if self.client.typedef.type_with_name_exists(struct_def.name):
LOG.info("Type with name %s already exists. Skipping.", struct_def['name']) LOG.info("Type with name %s already exists. Skipping.", struct_def.name)
else: else:
types_to_create['structDefs'].append(struct_def) types_to_create.structDefs.append(struct_def)
for classification_def in type_def['classificationDefs']: for classification_def in type_def.classificationDefs:
if self.client.typedef.type_with_name_exists(classification_def['name']): if self.client.typedef.type_with_name_exists(classification_def.name):
LOG.info("Type with name %s already exists. Skipping.", classification_def['name']) LOG.info("Type with name %s already exists. Skipping.", classification_def.name)
else: else:
types_to_create['classificationDefs'].append(classification_def) types_to_create.classificationDefs.append(classification_def)
for entity_def in type_def['entityDefs']: for entity_def in type_def.entityDefs:
if self.client.typedef.type_with_name_exists(entity_def['name']): if self.client.typedef.type_with_name_exists(entity_def.name):
LOG.info("Type with name %s already exists. Skipping.", entity_def['name']) LOG.info("Type with name %s already exists. Skipping.", entity_def.name)
else: else:
types_to_create['entityDefs'].append(entity_def) types_to_create.entityDefs.append(entity_def)
for relationship_def in type_def['relationshipDefs']: for relationship_def in type_def.relationshipDefs:
if self.client.typedef.type_with_name_exists(relationship_def['name']): if self.client.typedef.type_with_name_exists(relationship_def.name):
LOG.info("Type with name %s already exists. Skipping.", relationship_def['name']) LOG.info("Type with name %s already exists. Skipping.", relationship_def.name)
else: else:
types_to_create['relationshipDefs'].append(relationship_def) types_to_create.relationshipDefs.append(relationship_def)
for business_metadata_def in type_def['businessMetadataDefs']: for business_metadata_def in type_def.businessMetadataDefs:
if self.client.typedef.type_with_name_exists(business_metadata_def['name']): if self.client.typedef.type_with_name_exists(business_metadata_def.name):
LOG.info("Type with name %s already exists. Skipping.", business_metadata_def['name']) LOG.info("Type with name %s already exists. Skipping.", business_metadata_def.name)
else: else:
types_to_create['businessMetadataDefs'].append(business_metadata_def) types_to_create.businessMetadataDefs.append(business_metadata_def)
return self.client.typedef.create_atlas_typedefs(types_to_create) return self.client.typedef.create_atlas_typedefs(types_to_create)
...@@ -20,19 +20,18 @@ ...@@ -20,19 +20,18 @@
NAME = "name" NAME = "name"
DESCRIPTION = "description" DESCRIPTION = "description"
PII_TAG = "sample_pii_Tag" PII_TAG = "sample_pii"
FINANCE_TAG = "sample_finance_Tag" FINANCE_TAG = "sample_finance"
CLASSIFICATION = "classification" METRIC_CLASSIFICATION = "sample_metric"
METRIC_CLASSIFICATION = "Metric"
DATABASE_TYPE = "sample_db_type" DATABASE_TYPE = "sample_db"
PROCESS_TYPE = "sample_process_type" PROCESS_TYPE = "sample_process"
TABLE_TYPE = "sample_table_type" TABLE_TYPE = "sample_table"
COLUMN_TYPE = "sample_column_type" COLUMN_TYPE = "sample_column"
TABLE_DATABASE_TYPE = "sample_Table_DB" TABLE_DATABASE_TYPE = "sample_db_tables"
TABLE_COLUMNS_TYPE = "sample_Table_Columns" TABLE_COLUMNS_TYPE = "sample_table_columns"
ENUM_TABLE_TYPE = "tableType" ENUM_TABLE_TYPE = "sample_tableType"
BUSINESS_METADATA_TYPE = "bmWithAllTypes" BUSINESS_METADATA_TYPE = "sample_bm"
BUSINESS_METADATA_TYPE_MV = "bmWithAllTypesMV" BUSINESS_METADATA_TYPE_MV = "sample_bm_mv"
STRUCT_TYPE_SERDE = "serdeType" STRUCT_TYPE_SERDE = "sample_serdeType"
\ No newline at end of file
# Atlas Python Client # Apache Atlas Python Client
This is a python library for Atlas. Users can integrate with Atlas using the python client. Python library for Apache Atlas.
Currently, compatible with Python 3.5+
## Installation ## Installation
Use the package manager [pip](https://pip.pypa.io/en/stable/) to install python client for Atlas. Use the package manager [pip](https://pip.pypa.io/en/stable/) to install Python client for Apache Atlas.
```bash ```bash
# After publishing apache-atlas use
> pip install apache-atlas > pip install apache-atlas
``` ```
...@@ -19,22 +16,146 @@ Verify if apache-atlas client is installed: ...@@ -19,22 +16,146 @@ Verify if apache-atlas client is installed:
Package Version Package Version
------------ --------- ------------ ---------
apache-atlas 0.0.1 apache-atlas 0.0.2
``` ```
## Usage ## Usage
```python create_glossary.py``` ```python atlas_example.py```
```python ```python
# create_glossary.py # atlas_example.py
import time
from apache_atlas.client.base_client import AtlasClient
from apache_atlas.model.instance import *
## Step 1: create a client to connect to Apache Atlas server
client = AtlasClient('http://localhost:21000', ('admin', 'atlasR0cks!'))
# For Kerberos authentication, use HTTPKerberosAuth as shown below
#
# from requests_kerberos import HTTPKerberosAuth
#
# client = AtlasClient('http://localhost:21000', HTTPKerberosAuth())
# to disable SSL certificate validation (not recommended for production use!)
#
# client.session.verify = False
## Step 2: Let's create a database entity
test_db = AtlasEntity({ 'typeName': 'hive_db' })
test_db.attributes = { 'name': 'test_db', 'clusterName': 'prod', 'qualifiedName': 'test_db@prod' }
entity_info = AtlasEntityWithExtInfo()
entity_info.entity = test_db
print('Creating test_db')
resp = client.entity.create_entity(entity_info)
guid_db = resp.get_assigned_guid(test_db.guid)
print(' created test_db: guid=' + guid_db)
## Step 3: Let's create a table entity, and two column entities - in one call
test_tbl = AtlasEntity({ 'typeName': 'hive_table' })
test_tbl.attributes = { 'name': 'test_tbl', 'qualifiedName': 'test_db.test_tbl@prod' }
test_tbl.relationshipAttributes = { 'db': AtlasRelatedObjectId({ 'guid': guid_db }) }
test_col1 = AtlasEntity({ 'typeName': 'hive_column' })
test_col1.attributes = { 'name': 'test_col1', 'type': 'string', 'qualifiedName': 'test_db.test_tbl.test_col1@prod' }
test_col1.relationshipAttributes = { 'table': AtlasRelatedObjectId({ 'guid': test_tbl.guid }) }
test_col2 = AtlasEntity({ 'typeName': 'hive_column' })
test_col2.attributes = { 'name': 'test_col2', 'type': 'string', 'qualifiedName': 'test_db.test_tbl.test_col2@prod' }
test_col2.relationshipAttributes = { 'table': AtlasRelatedObjectId({ 'guid': test_tbl.guid }) }
entities_info = AtlasEntitiesWithExtInfo()
entities_info.entities = [ test_tbl, test_col1, test_col2 ]
print('Creating test_tbl')
resp = client.entity.create_entities(entities_info)
guid_tbl = resp.get_assigned_guid(test_tbl.guid)
guid_col1 = resp.get_assigned_guid(test_col1.guid)
guid_col2 = resp.get_assigned_guid(test_col2.guid)
print(' created test_tbl: guid=' + guid_tbl)
print(' created test_tbl.test_col1: guid=' + guid_col1)
print(' created test_tbl.test_col2: guid=' + guid_col2)
## Step 4: Let's create a view entity that feeds from the table created earlier
# Also create a lineage between the table and the view, and lineages between their columns as well
test_view = AtlasEntity({ 'typeName': 'hive_table' })
test_view.attributes = { 'name': 'test_view', 'qualifiedName': 'test_db.test_view@prod' }
test_view.relationshipAttributes = { 'db': AtlasRelatedObjectId({ 'guid': guid_db }) }
test_view_col1 = AtlasEntity({ 'typeName': 'hive_column' })
test_view_col1.attributes = { 'name': 'test_col1', 'type': 'string', 'qualifiedName': 'test_db.test_view.test_col1@prod' }
test_view_col1.relationshipAttributes = { 'table': AtlasRelatedObjectId({ 'guid': test_view.guid }) }
test_view_col2 = AtlasEntity({ 'typeName': 'hive_column' })
test_view_col2.attributes = { 'name': 'test_col2', 'type': 'string', 'qualifiedName': 'test_db.test_view.test_col2@prod' }
test_view_col2.relationshipAttributes = { 'table': AtlasRelatedObjectId({ 'guid': test_view.guid }) }
test_process = AtlasEntity({ 'typeName': 'hive_process' })
test_process.attributes = { 'name': 'create_test_view', 'userName': 'admin', 'operationType': 'CREATE', 'qualifiedName': 'create_test_view@prod' }
test_process.attributes['queryText'] = 'create view test_view as select * from test_tbl'
test_process.attributes['queryPlan'] = '<queryPlan>'
test_process.attributes['queryId'] = '<queryId>'
test_process.attributes['startTime'] = int(time.time() * 1000)
test_process.attributes['endTime'] = int(time.time() * 1000)
test_process.relationshipAttributes = { 'inputs': [ AtlasRelatedObjectId({ 'guid': guid_tbl }) ], 'outputs': [ AtlasRelatedObjectId({ 'guid': test_view.guid }) ] }
test_col1_lineage = AtlasEntity({ 'typeName': 'hive_column_lineage' })
test_col1_lineage.attributes = { 'name': 'test_view.test_col1 lineage', 'depenendencyType': 'read', 'qualifiedName': 'test_db.test_view.test_col1@prod' }
test_col1_lineage.attributes['query'] = { 'guid': test_process.guid }
test_col1_lineage.relationshipAttributes = { 'inputs': [ AtlasRelatedObjectId({ 'guid': guid_col1 }) ], 'outputs': [ AtlasRelatedObjectId({ 'guid': test_view_col1.guid }) ] }
test_col2_lineage = AtlasEntity({ 'typeName': 'hive_column_lineage' })
test_col2_lineage.attributes = { 'name': 'test_view.test_col2 lineage', 'depenendencyType': 'read', 'qualifiedName': 'test_db.test_view.test_col2@prod' }
test_col2_lineage.attributes['query'] = { 'guid': test_process.guid }
test_col2_lineage.relationshipAttributes = { 'inputs': [ AtlasRelatedObjectId({ 'guid': guid_col2 }) ], 'outputs': [ AtlasRelatedObjectId({ 'guid': test_view_col2.guid }) ] }
entities_info = AtlasEntitiesWithExtInfo()
entities_info.entities = [ test_process, test_col1_lineage, test_col2_lineage ]
entities_info.add_referenced_entity(test_view)
entities_info.add_referenced_entity(test_view_col1)
entities_info.add_referenced_entity(test_view_col2)
print('Creating test_view')
resp = client.entity.create_entities(entities_info)
guid_view = resp.get_assigned_guid(test_view.guid)
guid_view_col1 = resp.get_assigned_guid(test_view_col1.guid)
guid_view_col2 = resp.get_assigned_guid(test_view_col2.guid)
guid_process = resp.get_assigned_guid(test_process.guid)
guid_col1_lineage = resp.get_assigned_guid(test_col1_lineage.guid)
guid_col2_lineage = resp.get_assigned_guid(test_col2_lineage.guid)
print(' created test_view: guid=' + guid_view)
print(' created test_view.test_col1: guid=' + guid_view_col1)
print(' created test_view.test_col2: guid=' + guid_view_col1)
print(' created test_view lineage: guid=' + guid_process)
print(' created test_col1 lineage: guid=' + guid_col1_lineage)
print(' created test_col2 lineage: guid=' + guid_col2_lineage)
## Step 5: Finally, cleanup by deleting entities created above
print('Deleting entities')
from apache_atlas.base_client import AtlasClient resp = client.entity.delete_entities_by_guids([ guid_col1_lineage, guid_col2_lineage, guid_process, guid_view, guid_tbl, guid_db ])
from apache_atlas.model.glossary import AtlasGlossary
client = AtlasClient("http://localhost:31000", "admin", "admin123") deleted_count = len(resp.mutatedEntities[EntityOperation.DELETE.name]) if resp and resp.mutatedEntities and EntityOperation.DELETE.name in resp.mutatedEntities else 0
glossary = AtlasGlossary(None, None, "Glossary_Test", "This is a test Glossary")
test_glossary = client.glossary.create_glossary(glossary)
print('Created Test Glossary with guid: ' + test_glossary.guid) print(' ' + str(deleted_count) + ' entities deleted')
``` ```
For more examples, checkout `sample-app` python project in atlas-examples module. For more examples, checkout `sample-app` python project in [atlas-examples](https://github.com/apache/atlas/blob/master/atlas-examples/sample-app/src/main/python/sample_client.py) module.
\ No newline at end of file
...@@ -19,31 +19,27 @@ ...@@ -19,31 +19,27 @@
import copy import copy
import os import os
from http import HTTPStatus
from requests import Session
import json import json
import logging import logging
import logging.config
from apache_atlas.utils import CustomEncoder, HttpMethod from requests import Session
from apache_atlas.client.typedef import TypeDefClient
from apache_atlas.client.discovery import DiscoveryClient from apache_atlas.client.discovery import DiscoveryClient
from apache_atlas.client.entity import EntityClient from apache_atlas.client.entity import EntityClient
from apache_atlas.client.glossary import GlossaryClient from apache_atlas.client.glossary import GlossaryClient
from apache_atlas.client.lineage import LineageClient from apache_atlas.client.lineage import LineageClient
from apache_atlas.client.relationship import RelationshipClient from apache_atlas.client.relationship import RelationshipClient
from apache_atlas.client.typedef import TypeDefClient
from apache_atlas.exceptions import AtlasServiceException from apache_atlas.exceptions import AtlasServiceException
from apache_atlas.utils import HttpMethod, HTTPStatus, type_coerce
LOG = logging.getLogger('apache_atlas') LOG = logging.getLogger('apache_atlas')
class AtlasClient: class AtlasClient:
def __init__(self, host, auth):
def __init__(self, host, username, password):
session = Session() session = Session()
session.auth = (username, password) session.auth = auth
self.host = host self.host = host
self.session = session self.session = session
...@@ -55,6 +51,9 @@ class AtlasClient: ...@@ -55,6 +51,9 @@ class AtlasClient:
self.glossary = GlossaryClient(self) self.glossary = GlossaryClient(self)
self.relationship = RelationshipClient(self) self.relationship = RelationshipClient(self)
logging.getLogger("requests").setLevel(logging.WARNING)
def call_api(self, api, response_type=None, query_params=None, request_obj=None): def call_api(self, api, response_type=None, query_params=None, request_obj=None):
params = copy.deepcopy(self.request_params) params = copy.deepcopy(self.request_params)
path = os.path.join(self.host, api.path) path = os.path.join(self.host, api.path)
...@@ -62,13 +61,11 @@ class AtlasClient: ...@@ -62,13 +61,11 @@ class AtlasClient:
params['headers']['Accept'] = api.consumes params['headers']['Accept'] = api.consumes
params['headers']['Content-type'] = api.produces params['headers']['Content-type'] = api.produces
print(path)
if query_params: if query_params:
params['params'] = query_params params['params'] = query_params
if request_obj: if request_obj:
params['data'] = json.dumps(request_obj, indent=4, cls=CustomEncoder) params['data'] = json.dumps(request_obj)
if LOG.isEnabledFor(logging.DEBUG): if LOG.isEnabledFor(logging.DEBUG):
LOG.debug("------------------------------------------------------") LOG.debug("------------------------------------------------------")
...@@ -92,7 +89,6 @@ class AtlasClient: ...@@ -92,7 +89,6 @@ class AtlasClient:
if response is None: if response is None:
return None return None
elif response.status_code == api.expected_status: elif response.status_code == api.expected_status:
if not response_type: if not response_type:
return None return None
...@@ -106,7 +102,7 @@ class AtlasClient: ...@@ -106,7 +102,7 @@ class AtlasClient:
if response_type == str: if response_type == str:
return json.dumps(response.json()) return json.dumps(response.json())
return response_type(**response.json()) return type_coerce(response.json(), response_type)
else: else:
return None return None
except Exception as e: except Exception as e:
...@@ -115,11 +111,9 @@ class AtlasClient: ...@@ -115,11 +111,9 @@ class AtlasClient:
LOG.exception("Exception occurred while parsing response with msg: %s", e) LOG.exception("Exception occurred while parsing response with msg: %s", e)
raise AtlasServiceException(api, response) raise AtlasServiceException(api, response)
elif response.status_code == HTTPStatus.SERVICE_UNAVAILABLE: elif response.status_code == HTTPStatus.SERVICE_UNAVAILABLE:
LOG.error("Atlas Service unavailable. HTTP Status: %s", HTTPStatus.SERVICE_UNAVAILABLE) LOG.error("Atlas Service unavailable. HTTP Status: %s", HTTPStatus.SERVICE_UNAVAILABLE)
return None return None
else: else:
raise AtlasServiceException(api, response) raise AtlasServiceException(api, response)
...@@ -17,10 +17,8 @@ ...@@ -17,10 +17,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus from apache_atlas.model.discovery import *
from apache_atlas.utils import API, HttpMethod, HTTPStatus
from apache_atlas.model.discovery import AtlasSearchResult, AtlasUserSavedSearch, AtlasSuggestionsResult, AtlasQuickSearchResult
from apache_atlas.utils import API, HttpMethod, BASE_URI
class DiscoveryClient: class DiscoveryClient:
...@@ -145,14 +143,14 @@ class DiscoveryClient: ...@@ -145,14 +143,14 @@ class DiscoveryClient:
return self.client.call_api(DiscoveryClient.UPDATE_SAVED_SEARCH, AtlasUserSavedSearch, None, saved_search) return self.client.call_api(DiscoveryClient.UPDATE_SAVED_SEARCH, AtlasUserSavedSearch, None, saved_search)
def delete_saved_search(self, guid): def delete_saved_search(self, guid):
return self.client.call_api(DiscoveryClient.DELETE_SAVED_SEARCH.format_map({'guid': guid})) return self.client.call_api(DiscoveryClient.DELETE_SAVED_SEARCH.format_path({'guid': guid}))
def execute_saved_search(self, user_name, search_name): def execute_saved_search(self, user_name, search_name):
query_params = {"user", user_name} query_params = {"user", user_name}
return self.client.call_api(DiscoveryClient.EXECUTE_SAVED_SEARCH_BY_NAME.format_map({'search_name': search_name}), return self.client.call_api(DiscoveryClient.EXECUTE_SAVED_SEARCH_BY_NAME.format_path({'search_name': search_name}),
AtlasSearchResult, query_params) AtlasSearchResult, query_params)
def execute_saved_search(self, search_guid): def execute_saved_search(self, search_guid):
return self.client.call_api(DiscoveryClient.EXECUTE_SAVED_SEARCH_BY_GUID.format_map({'search_guid': search_guid}), return self.client.call_api(DiscoveryClient.EXECUTE_SAVED_SEARCH_BY_GUID.format_path({'search_guid': search_guid}),
AtlasSearchResult) AtlasSearchResult)
\ No newline at end of file
...@@ -17,13 +17,8 @@ ...@@ -17,13 +17,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus from apache_atlas.model.instance import *
from apache_atlas.utils import *
from apache_atlas.model.entity import AtlasEntityWithExtInfo, AtlasEntitiesWithExtInfo, AtlasEntityHeader, \
AtlasClassifications, AtlasEntityHeaders, EntityMutationResponse
from apache_atlas.utils import API, HttpMethod, BASE_URI, APPLICATION_OCTET_STREAM, APPLICATION_JSON, \
MULTIPART_FORM_DATA, attributes_to_params, list_attributes_to_params
class EntityClient: class EntityClient:
......
...@@ -17,10 +17,8 @@ ...@@ -17,10 +17,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus from apache_atlas.model.glossary import *
from apache_atlas.utils import *
from apache_atlas.model.glossary import AtlasGlossaryCategory, AtlasGlossaryTerm, AtlasGlossary, AtlasGlossaryExtInfo
from apache_atlas.utils import BASE_URI, API, HttpMethod, APPLICATION_JSON, APPLICATION_OCTET_STREAM, MULTIPART_FORM_DATA
class GlossaryClient: class GlossaryClient:
...@@ -142,7 +140,7 @@ class GlossaryClient: ...@@ -142,7 +140,7 @@ class GlossaryClient:
def get_related_categories(self, category_guid, sort_by_attribute, limit, offset): def get_related_categories(self, category_guid, sort_by_attribute, limit, offset):
query_params = {GlossaryClient.LIMIT: limit, GlossaryClient.OFFSET: offset, "sort": sort_by_attribute} query_params = {GlossaryClient.LIMIT: limit, GlossaryClient.OFFSET: offset, "sort": sort_by_attribute}
return self.client.call_api(GlossaryClient.GET_RELATED_CATEGORIES.format_map({'category_guid': category_guid}), return self.client.call_api(GlossaryClient.GET_RELATED_CATEGORIES.format_path({'category_guid': category_guid}),
dict, query_params) dict, query_params)
def create_glossary(self, glossary): def create_glossary(self, glossary):
......
...@@ -17,10 +17,8 @@ ...@@ -17,10 +17,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus from apache_atlas.model.lineage import *
from apache_atlas.utils import *
from apache_atlas.model.lineage import AtlasLineageInfo
from apache_atlas.utils import BASE_URI, API, HttpMethod, attributes_to_params
class LineageClient: class LineageClient:
......
...@@ -17,10 +17,8 @@ ...@@ -17,10 +17,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus from apache_atlas.model.relationship import *
from apache_atlas.utils import *
from apache_atlas.model.relationship import AtlasRelationshipWithExtInfo, AtlasRelationship
from apache_atlas.utils import BASE_URI, API, HttpMethod
class RelationshipClient: class RelationshipClient:
......
...@@ -17,11 +17,8 @@ ...@@ -17,11 +17,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from http import HTTPStatus from apache_atlas.model.typedef import *
from apache_atlas.utils import *
from apache_atlas.utils import API, HttpMethod, BASE_URI
from apache_atlas.model.typedef import AtlasEnumDef, AtlasClassificationDef, AtlasEntityDef, AtlasStructDef, \
AtlasRelationshipDef, AtlasBusinessMetadataDef, AtlasTypesDef, AtlasBaseTypeDef
class TypeDefClient: class TypeDefClient:
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
class AtlasServiceException(Exception): class AtlasServiceException(Exception):
"""Exception raised for errors in API calls. """Exception raised for errors in API calls.
...@@ -29,14 +30,12 @@ class AtlasServiceException(Exception): ...@@ -29,14 +30,12 @@ class AtlasServiceException(Exception):
msg = "" msg = ""
if api: if api:
msg = "Metadata service API {method} : {path} failed".format_map({'method': api.method, 'path': api.path}) msg = "Metadata service API {method} : {path} failed".format(**{'method': api.method, 'path': api.path})
if response.content: if response.content:
status = response.status_code if response.status_code else -1 status = response.status_code if response.status_code else -1
msg = "Metadata service API with url {url} and method {method} : failed with status {status} and " \ msg = "Metadata service API with url {url} and method {method} : failed with status {status} and " \
"Response Body is :{response}". \ "Response Body is :{response}". \
format_map({'url': response.url, 'method': api.method, 'status': status, 'response': response.json()}) format(**{'url': response.url, 'method': api.method, 'status': status, 'response': response.json()})
self.message = msg
super().__init__(self.message) Exception.__init__(self, msg)
\ No newline at end of file
...@@ -18,158 +18,183 @@ ...@@ -18,158 +18,183 @@
# limitations under the License. # limitations under the License.
import enum import enum
import sys
from apache_atlas.utils import AtlasBaseModelObject
class SearchFilter:
sortType_enum = enum.Enum('sortType_enum', 'NONE ASC DESC', module=__name__)
def __init__(self, params=None, startIndex=0, maxRows=sys.maxsize, getCount=True, sortBy=None, sortType=None):
self.params = params if params is not None else {}
self.startIndex = startIndex
self.maxRows = maxRows
self.getCount = getCount
self.sortBy = sortBy
self.sortType = sortType
class AtlasSearchResult:
queryType_enum = enum.Enum('queryType_enum', 'DSL FULL_TEXT GREMLIN BASIC ATTRIBUTE RELATIONSHIP', module=__name__)
def __init__(self, queryType=None, searchParameters=None, queryText=None, type=None, classification=None,
entities=None, attributes=None, fullTextResult=None, referredEntities=None, approximateCount=None):
self.queryType = queryType if queryType is not None else AtlasSearchResult.queryType_enum.BASIC.name
self.searchParameters = searchParameters
self.queryText = queryText
self.type = type
self.classification = classification
self.entities = entities
self.attributes = attributes
self.fullTextResult = fullTextResult if fullTextResult is not None else []
self.referredEntities = referredEntities if fullTextResult is not None else {}
self.approximateCount = approximateCount
class SearchParameters:
sortOrder_enum = enum.Enum('sortOrder_enum', 'ASCENDING DESCENDING', module=__name__)
def __init__(self, query=None, typeName=None, classification=None, termName=None, sortBy=None, excludeDeletedEntities=None,
includeClassificationAttributes=None, includeSubTypes=None, includeSubClassifications=None, limit=None,
offset=None, entityFilters=None, tagFilters=None, attributes=None, sortOrder=None):
self.query = query
self.typeName = typeName
self.classification = classification
self.termName = termName
self.sortBy = sortBy
self.excludeDeletedEntities = excludeDeletedEntities
self.includeClassificationAttributes = includeClassificationAttributes
self.includeSubTypes = includeSubTypes
self.includeSubClassifications = includeSubClassifications
self.limit = limit
self.offset = offset
self.entityFilters = entityFilters
self.tagFilters = tagFilters
self.attributes = attributes if attributes is not None else set()
self.sortOrder = sortOrder
class FilterCriteria:
operator_enum = enum.Enum('operator_enum',
'< > <= >= = != in like startsWith endsWith contains not_contains containsAny containsAll isNull notNull',
module=__name__)
condition_enum = enum.Enum('condition_enum', 'AND OR', module=__name__)
def __init__(self, attributeName=None, operator=None, attributeValue=None, condition=None, criterion=None):
self.attributeName = attributeName
self.operator = operator
self.attributeValue = attributeValue
self.condition = condition
self.criterion = criterion if criterion is not None else []
from apache_atlas.model.enums import *
from apache_atlas.model.instance import *
from apache_atlas.utils import *
class Operator(enum.Enum):
LT = ("<", "lt")
GT = ('>', 'gt')
LTE = ('<=', 'lte')
GTE = ('>=', 'gte')
EQ = ('=', 'eq')
NEQ = ('!=', 'neq')
IN = ('in', 'IN')
LIKE = ('like', 'LIKE')
STARTS_WITH = ('startsWith', 'STARTSWITH', 'begins_with', 'BEGINS_WITH')
ENDS_WITH = ('endsWith', 'ENDSWITH', 'ends_with', 'ENDS_WITH')
CONTAINS = ('contains', 'CONTAINS')
NOT_CONTAINS = ('not_contains', 'NOT_CONTAINS')
CONTAINS_ANY = ('containsAny', 'CONTAINSANY', 'contains_any', 'CONTAINS_ANY')
CONTAINS_ALL = ('containsAll', 'CONTAINSALL', 'contains_all', 'CONTAINS_ALL')
IS_NULL = ('isNull', 'ISNULL', 'is_null', 'IS_NULL')
NOT_NULL = ('notNull', 'NOTNULL', 'not_null', 'NOT_NULL')
class AtlasAggregationEntry(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
class SortOrder(enum.Enum): self.name = attrs.get('name')
sort_order = enum.Enum('sort_order', 'ASCENDING DESCENDING', module=__name__) self.name = attrs.get('count')
class AtlasQuickSearchResult(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.searchResults = attrs.get('searchResults')
self.aggregationMetrics = attrs.get('aggregationMetrics')
def type_coerce_attrs(self):
super(AtlasQuickSearchResult, self).type_coerce_attrs()
self.searchResults = type_coerce(self.searchResults, AtlasSearchResult)
self.aggregationMetrics = type_coerce_dict_list(self.aggregationMetrics, AtlasAggregationEntry)
class AtlasSearchResult(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.queryType = non_null(attrs.get('queryType'), QueryType.BASIC.name)
self.searchParameters = attrs.get('searchParameters')
self.queryText = attrs.get('queryText')
self.type = attrs.get('type')
self.classification = attrs.get('classification')
self.entities = attrs.get('entities')
self.attributes = attrs.get('attributes')
self.fullTextResult = attrs.get('fullTextResult')
self.referredEntities = attrs.get('referredEntities')
self.approximateCount = non_null(attrs.get('approximateCount'), -1)
def type_coerce_attrs(self):
super(AtlasSearchResult, self).type_coerce_attrs()
self.entities = type_coerce_list(self.entities, AtlasEntityHeader)
self.attributes = type_coerce(self.attributes, AttributeSearchResult)
self.referredEntities = type_coerce_dict(self.referredEntities, AtlasEntityHeader)
class AttributeSearchResult(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.name = attrs.get('name')
self.values = attrs.get('values')
class AttributeSearchResult:
def __init__(self, name=None, values=None): class AtlasFullTextResult(AtlasBase):
self.name = name def __init__(self, attrs={}):
self.values = values if values is not None else [] AtlasBase.__init__(self, attrs)
self.entity = attrs.get('entity')
self.score = attrs.get('score')
class AtlasFullTextResult: def type_coerce_attrs(self):
super(AtlasFullTextResult, self).type_coerce_attrs()
def __init__(self, entity=None, score=None): self.entity = type_coerce(self.criterion, AtlasEntityHeader)
self.entity = entity
self.score = score
class AtlasQuickSearchResult: class AtlasSuggestionsResult(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
def __init__(self, searchResults=None, aggregationMetrics=None): self.suggestions = attrs.get('suggestions')
self.searchResults = searchResults self.prefixString = attrs.get('prefixString')
self.aggregationMetrics = aggregationMetrics if aggregationMetrics is not None else {} self.fieldName = attrs.get('fieldName')
class AtlasAggregationEntry: class QuickSearchParameters(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
def __init__(self, name=None, count=None): self.query = attrs.get('query')
self.name = name self.typeName = attrs.get('typeName')
self.count = count self.entityFilters = attrs.get('entityFilters')
self.includeSubTypes = attrs.get('includeSubTypes')
self.excludeDeletedEntities = attrs.get('excludeDeletedEntities')
self.offset = attrs.get('offset')
self.limit = attrs.get('limit')
self.attributes = attrs.get('attributes')
def type_coerce_attrs(self):
super(QuickSearchParameters, self).type_coerce_attrs()
class QuickSearchParameters: self.entityFilters = type_coerce(self.entityFilters, FilterCriteria)
def __init__(self, query=None, typeName=None, entityFilters=None, includeSubTypes=None,
excludeDeletedEntities=None, offset=None, limit=None, attributes=None):
self.query = query
self.typeName = typeName
self.entityFilters = entityFilters
self.includeSubTypes = includeSubTypes
self.excludeDeletedEntities = excludeDeletedEntities
self.offset = offset
self.limit = limit
self.attributes = attributes if attributes is not None else set()
class SearchParameters(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
class AtlasSuggestionsResult: self.query = attrs.get('query')
self.typeName = attrs.get('typeName')
self.classification = attrs.get('classification')
self.termName = attrs.get('termName')
self.sortBy = attrs.get('sortBy')
self.excludeDeletedEntities = attrs.get('excludeDeletedEntities')
self.includeClassificationAttributes = attrs.get('includeClassificationAttributes')
self.includeSubTypes = non_null(attrs.get('includeSubTypes'), True)
self.includeSubClassifications = non_null(attrs.get('includeSubClassifications'), True)
self.limit = attrs.get('limit')
self.offset = attrs.get('offset')
self.entityFilters = attrs.get('entityFilters')
self.tagFilters = attrs.get('tagFilters')
self.attributes = attrs.get('attributes')
self.sortOrder = attrs.get('sortOrder')
def __init__(self, suggestions=None, prefixString=None, fieldName=None): def type_coerce_attrs(self):
self.suggestions = suggestions if suggestions is not None else [] super(SearchParameters, self).type_coerce_attrs()
self.prefixString = prefixString
self.fieldName = fieldName self.entityFilters = type_coerce(self.entityFilters, FilterCriteria)
self.tagFilters = type_coerce(self.tagFilters, FilterCriteria)
class FilterCriteria(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.attributeName = attrs.get('attributeName')
self.operator = attrs.get('operator')
self.attributeValue = attrs.get('attributeValue')
self.condition = attrs.get('condition')
self.criterion = attrs.get('criterion')
def type_coerce_attrs(self):
super(FilterCriteria, self).type_coerce_attrs()
self.criterion = type_coerce(self.criterion, FilterCriteria)
class AtlasUserSavedSearch(AtlasBaseModelObject): class AtlasUserSavedSearch(AtlasBaseModelObject):
saved_search_type_enum = enum.Enum('saved_search_type_enum', 'BASIC ADVANCED', module=__name__) def __init__(self, attrs={}):
AtlasBaseModelObject.__init__(self, attrs)
self.ownerName = attrs.get('ownerName')
self.name = attrs.get('name')
self.searchType = attrs.get('searchType')
self.searchParameters = attrs.get('searchParameters')
self.uiParameters = attrs.get('uiParameters')
def type_coerce_attrs(self):
super(AtlasUserSavedSearch, self).type_coerce_attrs()
self.searchParameters = type_coerce(self.searchParameters, SearchParameters)
class Operator(enum.Enum):
LT = ("<", "lt")
GT = ('>', 'gt')
LTE = ('<=', 'lte')
GTE = ('>=', 'gte')
EQ = ('=', 'eq')
NEQ = ('!=', 'neq')
IN = ('in', 'IN')
LIKE = ('like', 'LIKE')
STARTS_WITH = ('startsWith', 'STARTSWITH', 'begins_with', 'BEGINS_WITH')
ENDS_WITH = ('endsWith', 'ENDSWITH', 'ends_with', 'ENDS_WITH')
CONTAINS = ('contains', 'CONTAINS')
NOT_CONTAINS = ('not_contains', 'NOT_CONTAINS')
CONTAINS_ANY = ('containsAny', 'CONTAINSANY', 'contains_any', 'CONTAINS_ANY')
CONTAINS_ALL = ('containsAll', 'CONTAINSALL', 'contains_all', 'CONTAINS_ALL')
IS_NULL = ('isNull', 'ISNULL', 'is_null', 'IS_NULL')
NOT_NULL = ('notNull', 'NOTNULL', 'not_null', 'NOT_NULL')
def __init__(self, guid=None, ownerName=None, name=None, searchType=None, searchParameters=None, uiParameters=None):
super().__init__(guid)
self.ownerName = ownerName class SortOrder(enum.Enum):
self.name = name sort_order = enum.Enum('sort_order', 'ASCENDING DESCENDING', module=__name__)
self.searchType = searchType
self.searchParameters = searchParameters
self.uiParameters = uiParameters
\ No newline at end of file
#!/usr/bin/env/python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
import enum
from apache_atlas.utils import s_nextId
class AtlasStruct:
def __init__(self, typeName=None, attributes=None):
self.typeName = typeName
self.attributes = attributes if attributes is not None else {}
class AtlasEntity(AtlasStruct):
status_enum = enum.Enum('status_enum', 'ACTIVE DELETED PURGED', module=__name__)
def __init__(self, typeName=None, attributes=None, guid=None, homeId=None, isIncomplete=None, provenanceType=None,
status=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None, version=None,
relationshipAttributes=None, classifications=None, meanings=None, customAttributes=None,
businessAttributes=None, labels=None, proxy=None):
super().__init__(typeName, attributes)
self.guid = guid if guid is not None else "-" + str(s_nextId)
self.homeId = homeId
self.isIncomplete = isIncomplete
self.provenanceType = provenanceType
self.status = status
self.createdBy = createdBy
self.updatedBy = updatedBy
self.createTime = createTime
self.updateTime = updateTime
self.version = version
self.relationshipAttributes = relationshipAttributes if relationshipAttributes is not None else {}
self.classifications = classifications if classifications is not None else []
self.meanings = meanings if meanings is not None else []
self.customAttributes = customAttributes if customAttributes is not None else {}
self.businessAttributes = businessAttributes if businessAttributes is not None else {}
self.labels = labels if labels is not None else set()
self.proxy = proxy
class AtlasEntityExtInfo:
def __init__(self, referredEntities=None):
self.referredEntities = referredEntities if referredEntities is not None else {}
class AtlasEntityWithExtInfo(AtlasEntityExtInfo):
def __init__(self, referredEntities=None, entity=None):
super().__init__(referredEntities)
self.entity = entity
class AtlasEntitiesWithExtInfo(AtlasEntityExtInfo):
def __init__(self, referredEntities=None, entities=None):
super().__init__(referredEntities)
self.entities = entities if entities is not None else {}
class AtlasEntityHeader(AtlasStruct):
status_enum = enum.Enum('status_enum', 'ACTIVE DELETED PURGED', module=__name__)
def __init__(self, typeName=None, attributes=None, guid=None, status=None, displayText=None, classificationNames=None,
classifications=None, meaningNames=None, meanings=None, isIncomplete=None, labels=None):
super().__init__(typeName, attributes)
self.guid = guid if guid is not None else "-" + str(s_nextId)
self.status = status
self.displayText = displayText
self.classificationNames = classificationNames if classificationNames is not None else []
self.classifications = classifications
self.meaningNames = meaningNames
self.meanings = meanings if meanings is not None else []
self.isIncomplete = isIncomplete
self.labels = labels if labels is not None else set()
class AtlasClassification(AtlasStruct):
entityStatus_enum = enum.Enum('entityStatus_enum', 'ACTIVE DELETED PURGED', module=__name__)
def __init__(self, typeName=None, attributes=None, entityGuid=None, entityStatus=None, propagate=None,
validityPeriods=None, removePropagationsOnEntityDelete=None):
self.typeName = typeName
self.attributes = attributes
self.entityGuid = entityGuid
self.entityStatus = entityStatus
self.propagate = propagate
self.validityPeriods = validityPeriods if validityPeriods is not None else []
self.removePropagationsOnEntityDelete = removePropagationsOnEntityDelete
class TimeBoundary:
def __init__(self, startTime=None, endTime=None, timeZone=None):
self.startTime = startTime
self.endTime = endTime
self.timeZone = timeZone
class Plist:
sortType_enum = enum.Enum('sortType_enum', 'NONE ASC DESC', module=__name__)
def __init__(self, list=None, startIndex=None, pageSize=None, totalCount=None, sortBy=None, sortType=None):
self.list = list
self.startIndex = startIndex
self.pageSize = pageSize
self.totalCount = totalCount
self.sortBy = sortBy
self.sortType = sortType
class AtlasClassifications(Plist):
sortType_enum = enum.Enum('sortType_enum', 'NONE ASC DESC', module=__name__)
def __init__(self, list=None, startIndex=None, pageSize=None, totalCount=None, sortBy=None, sortType=None):
super().__init__(list, startIndex, pageSize, totalCount, sortBy, sortType)
class AtlasEntityHeaders:
def __init__(self, guidHeaderMap=None):
self.guidHeaderMap = guidHeaderMap if guidHeaderMap is not None else {}
class EntityMutationResponse:
def __init__(self, mutatedEntities=None, guidAssignments=None):
self.mutatedEntities = mutatedEntities if mutatedEntities is not None else {}
self.guidAssignments = guidAssignments if guidAssignments is not None else {}
class EntityMutations:
entity_operation_enum = enum.Enum('entity_operation_enum', 'CREATE UPDATE PARTIAL_UPDATE DELETE PURGE', module=__name__)
def __init__(self, entity_mutations):
self.entity_mutations = entity_mutations if entity_mutations is not None else []
class EntityMutation:
def __init__(self, op, entity):
self.op = op
self.entity = entity
\ No newline at end of file
#!/usr/bin/env/python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicabwle 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.
import enum
class AtlasTermAssignmentStatus(enum.Enum):
DISCOVERED = 0
PROPOSED = 1
IMPORTED = 2
VALIDATED = 3
DEPRECATED = 4
OBSOLETE = 5
OTHER = 6
class AtlasTermRelationshipStatus(enum.Enum):
DRAFT = 0
ACTIVE = 1
DEPRECATED = 2
OBSOLETE = 3
OTHER = 99
class TypeCategory(enum.Enum):
PRIMITIVE = 0
OBJECT_ID_TYPE = 1
ENUM = 2
STRUCT = 3
CLASSIFICATION = 4
ENTITY = 5
ARRAY = 6
MAP = 7
RELATIONSHIP = 8
BUSINESS_METADATA = 9
class Cardinality(enum.Enum):
SINGLE = 0
LIST = 1
SET = 2
class Condition(enum.Enum):
AND = 0
OR = 1
class EntityOperation(enum.Enum):
CREATE = 0
UPDATE = 1
PARTIAL_UPDATE = 2
DELETE = 3
PURGE = 4
class EntityStatus(enum.Enum):
ACTIVE = 0
DELETED = 1
PURGED = 2
class IndexType(enum.Enum):
DEFAULT = 0
STRING = 1
class LineageDirection(enum.Enum):
INPUT = 0
OUTPUT = 1
BOTH = 2
class Operator(enum.Enum):
LT = ("<", "lt")
GT = ('>', 'gt')
LTE = ('<=', 'lte')
GTE = ('>=', 'gte')
EQ = ('=', 'eq')
NEQ = ('!=', 'neq')
IN = ('in', 'IN')
LIKE = ('like', 'LIKE')
STARTS_WITH = ('startsWith', 'STARTSWITH', 'begins_with', 'BEGINS_WITH')
ENDS_WITH = ('endsWith', 'ENDSWITH', 'ends_with', 'ENDS_WITH')
CONTAINS = ('contains', 'CONTAINS')
NOT_CONTAINS = ('not_contains', 'NOT_CONTAINS')
CONTAINS_ANY = ('containsAny', 'CONTAINSANY', 'contains_any', 'CONTAINS_ANY')
CONTAINS_ALL = ('containsAll', 'CONTAINSALL', 'contains_all', 'CONTAINS_ALL')
IS_NULL = ('isNull', 'ISNULL', 'is_null', 'IS_NULL')
NOT_NULL = ('notNull', 'NOTNULL', 'not_null', 'NOT_NULL')
class PropagateTags(enum.Enum):
NONE = 0
ONE_TO_TWO = 1
TWO_TO_ONE = 2
BOTH = 3
class QueryType(enum.Enum):
DSL = 0
FULL_TEXT = 1
GREMLIN = 2
BASIC = 3
ATTRIBUTE = 4
RELATIONSHIP = 5
class RelationshipCategory(enum.Enum):
ASSOCIATION = 0
AGGREGATION = 1
COMPOSITION = 2
class RelationshipStatus(enum.Enum):
ACTIVE = 0
DELETED = 1
class SavedSearchType(enum.Enum):
BASIC = 0
ADVANCED = 1
class SortOrder(enum.Enum):
ASCENDING = 0
DESCENDING = 1
class SortType(enum.Enum):
NONE = 0
ASC = 1
DESC = 2
...@@ -17,191 +17,201 @@ ...@@ -17,191 +17,201 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import enum import apache_atlas.model.instance
from apache_atlas.utils import AtlasBaseModelObject from apache_atlas.model.misc import *
from apache_atlas.utils import *
class AtlasGlossaryBaseObject(AtlasBaseModelObject): class AtlasGlossaryBaseObject(AtlasBaseModelObject):
def __init__(self, attrs={}):
AtlasBaseModelObject.__init__(self, attrs)
def __init__(self, guid=None, qualifiedName=None, name=None, shortDescription=None, self.qualifiedName = attrs.get('qualifiedName')
longDescription=None, additionalAttributes=None, classifications=None): self.name = attrs.get('name')
self.shortDescription = attrs.get('shortDescription')
self.longDescription = attrs.get('longDescription')
self.additionalAttributes = attrs.get('additionalAttributes')
self.classifications = attrs.get('classifications')
super().__init__(guid) def type_coerce_attrs(self):
super(AtlasGlossaryBaseObject, self).type_coerce_attrs()
self.qualifiedName = qualifiedName self.classifications = type_coerce_list(self.classifications, apache_atlas.model.instance.AtlasClassification)
self.name = name
self.shortDescription = shortDescription
self.longDescription = longDescription
self.additionalAttributes = additionalAttributes if additionalAttributes is not None else {}
self.classifications = classifications if classifications is not None else []
class AtlasGlossary(AtlasGlossaryBaseObject): class AtlasGlossary(AtlasGlossaryBaseObject):
def __init__(self, attrs={}):
AtlasGlossaryBaseObject.__init__(self, attrs)
def __init__(self, guid=None, qualifiedName=None, name=None, shortDescription=None, longDescription=None, self.language = attrs.get('language')
additionalAttributes=None, classifications=None, language=None, usage=None, terms=None, categories=None): self.usage = attrs.get('usage')
self.terms = attrs.get('terms')
self.categories = attrs.get('categories')
super().__init__(guid, qualifiedName, name, shortDescription, longDescription, additionalAttributes, classifications) def type_coerce_attrs(self):
super(AtlasGlossary, self).type_coerce_attrs()
self.language = language self.terms = type_coerce_list(self.classifications, AtlasRelatedTermHeader)
self.usage = usage self.categories = type_coerce_list(self.categories, AtlasRelatedCategoryHeader)
self.terms = terms if terms is not None else set()
self.categories = categories if categories is not None else set()
class AtlasRelatedTermHeader: class AtlasGlossaryExtInfo(AtlasGlossary):
status_enum = enum.Enum('status_enum', 'DRAFT ACTIVE DEPRECATED OBSOLETE OTHER', module=__name__) def __init__(self, attrs={}):
AtlasGlossary.__init__(self, attrs)
def __init__(self, termGuid=None, relationGuid=None, displayText=None, description=None,
expression=None, steward=None, source=None, status=None):
self.termGuid = termGuid
self.relationGuid = relationGuid
self.displayText = displayText
self.description = description
self.expression = expression
self.steward = steward
self.source = source
self.status = status
self.termInfo = attrs.get('termInfo')
self.categoryInfo = attrs.get('categoryInfo')
class AtlasRelatedCategoryHeader: def type_coerce_attrs(self):
super(AtlasGlossaryExtInfo, self).type_coerce_attrs()
def __init__(self, categoryGuid=None, parentCategoryGuid=None, relationGuid=None, displayText=None, description=None): self.termInfo = type_coerce_dict(self.termInfo, AtlasGlossaryTerm)
self.categoryGuid = categoryGuid self.categoryInfo = type_coerce_dict(self.categoryInfo, AtlasGlossaryCategory)
self.parentCategoryGuid = parentCategoryGuid
self.relationGuid = relationGuid
self.displayText = displayText
self.description = description
class AtlasGlossaryExtInfo(AtlasGlossary): class AtlasGlossaryCategory(AtlasGlossaryBaseObject):
def __init__(self, attrs):
AtlasGlossaryBaseObject.__init__(self, attrs)
def __init__(self, guid=None, qualifiedName=None, name=None, shortDescription=None, longDescription=None, additionalAttributes=None, # Inherited attributes from relations
classifications=None, language=None, usage=None, terms=None, categories=None, termInfo=None, categoryInfo=None): self.anchor = attrs.get('anchor')
super().__init__(guid, qualifiedName, name, shortDescription, longDescription, # Category hierarchy links
additionalAttributes, classifications, language, usage, terms, categories) self.parentCategory = attrs.get('parentCategory')
self.childrenCategories = attrs.get('childrenCategories')
self.termInfo = termInfo if termInfo is not None else {} # Terms associated with this category
self.categoryInfo = categoryInfo if categoryInfo is not None else {} self.terms = attrs.get('terms')
def type_coerce_attrs(self):
super(AtlasGlossaryCategory, self).type_coerce_attrs()
class AtlasTermRelationshipStatus(enum.Enum): self.anchor = type_coerce(self.anchor, AtlasGlossaryHeader)
DRAFT = 0 self.parentCategory = type_coerce(self.parentCategory, AtlasRelatedCategoryHeader)
ACTIVE = 1 self.childrenCategories = type_coerce_list(self.childrenCategories, AtlasRelatedCategoryHeader)
DEPRECATED = 2 self.terms = type_coerce_list(self.terms, AtlasRelatedTermHeader)
OBSOLETE = 3
OTHER = 99
class AtlasGlossaryTerm(AtlasGlossaryBaseObject): class AtlasGlossaryTerm(AtlasGlossaryBaseObject):
def __init__(self, attrs={}):
def __init__(self, guid=None, qualifiedName=None, name=None, shortDescription=None, longDescription=None, AtlasGlossaryBaseObject.__init__(self, attrs)
additionalAttributes=None, classifications=None, examples=None, abbreviation=None, usage=None, anchor=None,
assignedEntities=None, categories=None, seeAlso=None, synonyms=None, antonyms=None, preferredTerms=None,
preferredToTerms=None, replacementTerms=None, replacedBy=None, translationTerms=None, translatedTerms=None,
isA=None, classifies=None, validValues=None, validValuesFor=None):
super().__init__(guid, qualifiedName, name, shortDescription, longDescription, additionalAttributes, classifications)
# Core attributes # Core attributes
self.examples = examples if examples is not None else [] self.examples = attrs.get('examples')
self.abbreviation = abbreviation self.abbreviation = attrs.get('abbreviation')
self.usage = usage self.usage = attrs.get('usage')
# Attributes derived from relationships # Attributes derived from relationships
self.anchor = anchor self.anchor = attrs.get('anchor')
self.assignedEntities = assignedEntities if assignedEntities is not None else set() self.assignedEntities = attrs.get('assignedEntities')
self.categories = categories if categories is not None else set() self.categories = attrs.get('categories')
# Related Terms # Related Terms
self.seeAlso = seeAlso if seeAlso is not None else set() self.seeAlso = attrs.get('seeAlso')
# Term Synonyms # Term Synonyms
self.synonyms = synonyms if synonyms is not None else set() self.synonyms = attrs.get('synonyms')
# Term antonyms # Term antonyms
self.antonyms = antonyms if antonyms is not None else set() self.antonyms = attrs.get('antonyms')
# Term preference # Term preference
self.preferredTerms = preferredTerms if preferredTerms is not None else set() self.preferredTerms = attrs.get('preferredTerms')
self.preferredToTerms = preferredToTerms if preferredToTerms is not None else set() self.preferredToTerms = attrs.get('preferredToTerms')
# Term replacements # Term replacements
self.replacementTerms = replacementTerms if replacementTerms is not None else set() self.replacementTerms = attrs.get('replacementTerms')
self.replacedBy = replacedBy if replacedBy is not None else set() self.replacedBy = attrs.get('replacedBy')
# Term translations # Term translations
self.translationTerms = translationTerms if translationTerms is not None else set() self.translationTerms = attrs.get('translationTerms')
self.translatedTerms = translatedTerms if translatedTerms is not None else set() self.translatedTerms = attrs.get('translatedTerms')
# Term classification # Term classification
self.isA = isA if isA is not None else set() self.isA = attrs.get('isA')
self.classifies = classifies if classifies is not None else set() self.classifies = attrs.get('classifies')
# Values for terms # Values for terms
self.validValues = validValues if validValues is not None else set() self.validValues = attrs.get('validValues')
self.validValuesFor = validValuesFor if validValuesFor is not None else set() self.validValuesFor = attrs.get('validValuesFor')
def type_coerce_attrs(self):
class AtlasGlossaryHeader: super(AtlasGlossaryTerm, self).type_coerce_attrs()
def __init__(self, glossaryGuid=None, relationGuid=None, displayText=None): self.anchor = type_coerce(self.anchor, AtlasGlossaryHeader)
self.glossaryGuid = glossaryGuid if glossaryGuid is not None else "" self.assignedEntities = type_coerce_list(self.assignedEntities, apache_atlas.model.instance.AtlasRelatedObjectId)
self.relationGuid = relationGuid self.categories = type_coerce_list(self.categories, AtlasTermCategorizationHeader)
self.displayText = displayText self.seeAlso = type_coerce_list(self.seeAlso, AtlasRelatedTermHeader)
self.synonyms = type_coerce_list(self.synonyms, AtlasRelatedTermHeader)
self.antonyms = type_coerce_list(self.antonyms, AtlasRelatedTermHeader)
class AtlasObjectId: self.preferredTerms = type_coerce_list(self.preferredTerms, AtlasRelatedTermHeader)
self.preferredToTerms = type_coerce_list(self.preferredToTerms, AtlasRelatedTermHeader)
def __init__(self, guid=None, typeName=None, uniqueAttributes=None): self.replacementTerms = type_coerce_list(self.replacementTerms, AtlasRelatedTermHeader)
self.guid = guid if guid is not None else "" self.replacedBy = type_coerce_list(self.replacedBy, AtlasRelatedTermHeader)
self.typeName = typeName self.translationTerms = type_coerce_list(self.translationTerms, AtlasRelatedTermHeader)
self.uniqueAttributes = uniqueAttributes if uniqueAttributes is not None else {} self.isA = type_coerce_list(self.isA, AtlasRelatedTermHeader)
self.classifies = type_coerce_list(self.classifies, AtlasRelatedTermHeader)
self.validValues = type_coerce_list(self.validValues, AtlasRelatedTermHeader)
self.validValuesFor = type_coerce_list(self.validValuesFor, AtlasRelatedTermHeader)
class AtlasGlossaryHeader(AtlasBase):
def __init__(self, attrs):
AtlasBase.__init__(self, attrs)
self.glossaryGuid = attrs.get('glossaryGuid')
self.relationGuid = attrs.get('relationGuid')
self.displayText = attrs.get('displayText')
class AtlasRelatedCategoryHeader(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.categoryGuid = attrs.get('categoryGuid')
self.parentCategoryGuid = attrs.get('parentCategoryGuid')
self.relationGuid = attrs.get('relationGuid')
self.displayText = attrs.get('displayText')
self.description = attrs.get('description')
class AtlasRelatedTermHeader(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.termGuid = attrs.get('termGuid')
self.relationGuid = attrs.get('relationGuid')
self.displayText = attrs.get('displayText')
self.description = attrs.get('description')
self.expression = attrs.get('expression')
self.steward = attrs.get('steward')
self.source = attrs.get('source')
self.status = attrs.get('status')
class AtlasTermAssignmentHeader(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.termGuid = attrs.get('termGuid')
self.relationGuid = attrs.get('relationGuid')
self.description = attrs.get('description')
self.displayText = attrs.get('displayText')
self.expression = attrs.get('expression')
self.createdBy = attrs.get('createdBy')
self.steward = attrs.get('steward')
self.source = attrs.get('source')
self.confidence = attrs.get('confidence')
class AtlasTermCategorizationHeader(AtlasBase):
def __init__(self, attrs):
AtlasBase.__init__(self, attrs)
self.categoryGuid = attrs.get('categoryGuid')
self.relationGuid = attrs.get('relationGuid')
self.description = attrs.get('description')
self.displayText = attrs.get('displayText')
self.status = attrs.get('status')
class AtlasRelatedObjectId(AtlasObjectId):
entityStatus_enum = enum.Enum('entityStatus_enum', 'ACTIVE DELETED PURGED', module=__name__)
relationshipStatus_enum = enum.Enum('relationshipStatus_enum', 'ACTIVE DELETED', module=__name__)
def __init__(self, guid=None, typeName=None, uniqueAttributes=None, entityStatus=None, displayText=None,
relationshipType=None, relationshipGuid=None, relationshipStatus=None, relationshipAttributes=None):
super().__init__(guid, typeName, uniqueAttributes)
self.entityStatus = entityStatus
self.displayText = displayText
self.relationshipType = relationshipType
self.relationshipGuid = relationshipGuid
self.relationshipStatus = relationshipStatus
self.relationshipAttributes = relationshipAttributes
class AtlasTermCategorizationHeader:
status_enum = enum.Enum('status_enum', 'DRAFT ACTIVE DEPRECATED OBSOLETE OTHER', module=__name__)
def __init__(self, categoryGuid=None, relationGuid=None, description=None, displayText=None, status=None):
self.categoryGuid = categoryGuid if categoryGuid is not None else ""
self.relationGuid = relationGuid
self.description = description
self.displayText = displayText
self.status = status
class AtlasGlossaryCategory(AtlasGlossaryBaseObject):
def __init__(self, guid=None, qualifiedName=None, name=None, shortDescription=None, longDescription=None,
additionalAttributes=None, classifications=None, anchor=None, parentCategory=None, childrenCategories=None, terms=None):
super().__init__(guid, qualifiedName, name, shortDescription, longDescription, additionalAttributes, classifications)
# Inherited attributes from relations
self.anchor = anchor
# Category hierarchy links
self.parentCategory = parentCategory
self.childrenCategories = childrenCategories
# Terms associated with this category
self.terms = terms if terms is not None else set()
\ No newline at end of file
#!/usr/bin/env/python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
import apache_atlas.model.glossary
from apache_atlas.model.enums import *
from apache_atlas.model.misc import *
from apache_atlas.utils import *
class AtlasStruct(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.typeName = attrs.get('typeName')
self.attributes = attrs.get('attributes')
def get_attribute(self, name):
return self.attributes[name] if self.attributes and name in self.attributes else None
def set_attribute(self, name, value):
if self.attributes is None:
self.attributes = {}
self.attributes[name] = value
def remove_attribute(self, name):
if name and self.attributes and name in self.attributes:
del self.attributes[name]
class AtlasEntity(AtlasStruct):
def __init__(self, attrs={}):
AtlasStruct.__init__(self, attrs)
self.guid = attrs.get('guid')
self.relationshipAttributes = attrs.get('relationshipAttributes')
self.classifications = attrs.get('classifications')
self.meanings = attrs.get('meanings')
self.customAttributes = attrs.get('customAttributes')
self.businessAttributes = attrs.get('businessAttributes')
self.labels = attrs.get('labels')
if self.guid is None:
self.guid = next_id()
def type_coerce_attrs(self):
super(AtlasEntity, self).type_coerce_attrs()
self.classifications = type_coerce_list(self.classifications, AtlasClassification)
self.meanings = type_coerce_list(self.meanings, apache_atlas.model.glossary.AtlasTermAssignmentHeader)
def get_relationship_attribute(self, name):
return self.relationshipAttributes[name] if self.relationshipAttributes and name in self.relationshipAttributes else None
def set_relationship_attribute(self, name, value):
if self.relationshipAttributes is None:
self.relationshipAttributes = {}
self.relationshipAttributes[name] = value
def remove_relationship_attribute(self, name):
if name and self.relationshipAttributes and name in self.relationshipAttributes:
del self.relationshipAttributes[name]
class AtlasEntityExtInfo(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.referredEntities = attrs.get('referredEntities')
def type_coerce_attrs(self):
super(AtlasEntityExtInfo, self).type_coerce_attrs()
self.referredEntities = type_coerce_dict(self.referredEntities, AtlasEntity)
def get_referenced_entity(self, guid):
return self.referredEntities[guid] if self.referredEntities and guid in self.referredEntities else None
def add_referenced_entity(self, entity):
if self.referredEntities is None:
self.referredEntities = {}
self.referredEntities[entity.guid] = entity
class AtlasEntityWithExtInfo(AtlasEntityExtInfo):
def __init__(self, attrs={}):
AtlasEntityExtInfo.__init__(self, attrs)
self.entity = attrs.get('entity')
def type_coerce_attrs(self):
super(AtlasEntityWithExtInfo, self).type_coerce_attrs()
self.entity = type_coerce(self.entity, AtlasEntity)
class AtlasEntitiesWithExtInfo(AtlasEntityExtInfo):
def __init__(self, attrs={}):
AtlasEntityExtInfo.__init__(self, attrs)
self.entities = attrs.get('entities')
def type_coerce_attrs(self):
super(AtlasEntitiesWithExtInfo, self).type_coerce_attrs()
self.entities = type_coerce_list(self.entity, AtlasEntity)
def add_entity(self, entity):
if self.entities is None:
self.entities = []
self.entities.append(entity)
class AtlasEntityHeader(AtlasStruct):
def __init__(self, attrs={}):
AtlasStruct.__init__(self, attrs)
self.guid = attrs.get('guid')
self.status = non_null(attrs.get('status'), EntityStatus.ACTIVE.name)
self.displayText = attrs.get('displayText')
self.classificationNames = attrs.get('classificationNames')
self.classifications = attrs.get('classifications')
self.meaningNames = attrs.get('meaningNames')
self.meanings = attrs.get('.meanings')
self.isIncomplete = non_null(attrs.get('isIncomplete'), False)
self.labels = attrs.get('labels')
if self.guid is None:
self.guid = next_id()
def type_coerce_attrs(self):
super(AtlasEntityHeader, self).type_coerce_attrs()
self.classifications = type_coerce_list(self.classifications, AtlasClassification)
self.meanings = type_coerce_list(self.meanings, apache_atlas.model.glossary.AtlasTermAssignmentHeader)
class AtlasClassification(AtlasStruct):
def __init__(self, attrs={}):
AtlasStruct.__init__(self, attrs)
self.entityGuid = attrs.get('entityGuid')
self.entityStatus = non_null(attrs.get('entityStatus'), EntityStatus.ACTIVE.name)
self.propagate = attrs.get('propagate');
self.validityPeriods = attrs.get('validityPeriods')
self.removePropagationsOnEntityDelete = attrs.get('removePropagationsOnEntityDelete')
def type_coerce_attrs(self):
super(AtlasClassification, self).type_coerce_attrs()
self.validityPeriods = type_coerce_list(self.validityPeriods, TimeBoundary)
class AtlasObjectId(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.guid = attrs.get('guid')
self.typeName = attrs.get('typeName')
self.uniqueAttributes = attrs.get('uniqueAttributes')
class AtlasRelatedObjectId(AtlasObjectId):
def __init__(self, attrs={}):
AtlasObjectId.__init__(self, attrs)
self.entityStatus = attrs.get('entityStatus')
self.displayText = attrs.get('displayText')
self.relationshipType = attrs.get('relationshipType')
self.relationshipGuid = attrs.get('relationshipGuid')
self.relationshipStatus = attrs.get('relationshipStatus')
self.relationshipAttributes = attrs.get('relationshipAttributes')
def type_coerce_attrs(self):
super(AtlasRelatedObjectId, self).type_coerce_attrs()
self.relationshipAttributes = type_coerce(self.relationshipAttributes, AtlasStruct)
class AtlasClassifications(Plist):
def __init__(self, attrs={}):
Plist.__init__(self, attrs)
def type_coerce_attrs(self):
super(AtlasClassifications, self).type_coerce_attrs()
PList.list = type_coerce_list(Plist.list, AtlasClassification)
class AtlasEntityHeaders(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.guidHeaderMap = attrs.get('guidHeaderMap')
def type_coerce_attrs(self):
super(AtlasEntityHeaders, self).type_coerce_attrs()
self.guidHeaderMap = type_coerce_dict(self.guidHeaderMap, AtlasEntityHeader)
class EntityMutationResponse(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.mutatedEntities = attrs.get('mutatedEntities')
self.guidAssignments = attrs.get('guidAssignments')
def type_coerce_attrs(self):
super(EntityMutationResponse, self).type_coerce_attrs()
self.mutatedEntities = type_coerce_dict_list(self.mutatedEntities, AtlasEntityHeader)
def get_assigned_guid(self, guid):
return self.guidAssignments.get(guid) if self.guidAssignments else None
class EntityMutations(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.entity_mutations = attrs.get('entity_mutations')
def type_coerce_attrs(self):
super(EntityMutations, self).type_coerce_attrs()
self.entity_mutations = type_coerce_list(self.entity_mutations, EntityMutation)
class EntityMutation(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.op = attrs.get('op')
self.entity = attrs.get('entity')
def type_coerce_attrs(self):
super(EntityMutation, self).type_coerce_attrs()
self.entity = type_coerce(self.entity, AtlasEntity)
class AtlasCheckStateRequest(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.entityGuids = attrs.get('entityGuids')
self.entityTypes = attrs.get('entityTypes')
self.fixIssues = attrs.get('fixIssues')
class AtlasCheckStateResult(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.entitiesScanned = attrs.get('entitiesScanned')
self.entitiesOk = attrs.get('entitiesOk')
self.entitiesFixed = attrs.get('entitiesFixed')
self.entitiesPartiallyFixed = attrs.get('entitiesPartiallyFixed')
self.entitiesNotFixed = attrs.get('entitiesNotFixed')
self.state = attrs.get('state')
self.entities = attrs.get('entities')
def type_coerce_attrs(self):
super(AtlasCheckStateResult, self).type_coerce_attrs()
self.entities = type_coerce(self.entities, AtlasEntityState)
class AtlasEntityState(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.guid = attrs.get('guid')
self.typeName = attrs.get('typeName')
self.name = attrs.get('name')
self.status = attrs.get('status')
self.state = attrs.get('state')
self.issues = attrs.get('issues')
...@@ -17,23 +17,32 @@ ...@@ -17,23 +17,32 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import enum from apache_atlas.model.instance import *
from apache_atlas.utils import *
class AtlasLineageInfo: class AtlasLineageInfo(AtlasBase):
lineageDirection_enum = enum.Enum('lineageDirection_enum', 'INPUT OUTPUT BOTH', module=__name__) def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
def __init__(self, baseEntityGuid=None, lineageDirection=None, lineageDepth=None, guidEntityMap=None, relations=None): self.baseEntityGuid = attrs.get('baseEntityGuid')
self.baseEntityGuid = baseEntityGuid self.lineageDirection = attrs.get('lineageDirection')
self.lineageDirection = lineageDirection self.lineageDepth = attrs.get('lineageDepth')
self.lineageDepth = lineageDepth self.guidEntityMap = attrs.get('guidEntityMap')
self.guidEntityMap = guidEntityMap if guidEntityMap is not None else {} self.relations = attrs.get('relations')
self.relations = relations if relations is not None else set()
class LineageRelation: def type_coerce_attrs(self):
super(AtlasLineageInfo, self).type_coerce_attrs()
def __init__(self, fromEntityId=None, toEntityId=None, relationshipId=None): self.guidEntityMap = type_coerce_dict(self.guidEntityMap, AtlasEntityHeader)
self.fromEntityId = fromEntityId self.relations = type_coerce_list(self.relations, LineageRelation)
self.toEntityId = toEntityId
self.relationshipId = relationshipId
\ No newline at end of file class LineageRelation(AtlasBase):
def __init__(self, attrs):
AtlasBase.__init__(self, attrs)
self.fromEntityId = attrs.get('fromEntityId')
self.toEntityId = attrs.get('toEntityId')
self.relationshipId = attrs.get('relationshipId')
#!/usr/bin/env/python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
from apache_atlas.utils import *
class AtlasMetrics(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.data = attrs.get('data')
#!/usr/bin/env/python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
import json
import sys
from apache_atlas.utils import *
class AtlasBase(dict):
def __init__(self, attrs):
pass
def __getattr__(self, attr):
return self.get(attr)
def __setattr__(self, key, value):
self.__setitem__(key, value)
def __setitem__(self, key, value):
super(AtlasBase, self).__setitem__(key, value)
self.__dict__.update({key: value})
def __delattr__(self, item):
self.__delitem__(item)
def __delitem__(self, key):
super(AtlasBase, self).__delitem__(key)
del self.__dict__[key]
def __repr__(self):
return json.dumps(self)
def type_coerce_attrs(self):
pass
class AtlasBaseModelObject(AtlasBase):
def __init__(self, members):
AtlasBase.__init__(self, members)
self.guid = members.get('guid')
if self.guid is None:
self.guid = next_id()
class TimeBoundary(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.startTime = attrs.get('startTime')
self.endTime = attrs.get('endTime')
self.timeZone = attrs.get('timeZone')
class Plist(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.list = non_null(attrs.get('list'), [])
self.startIndex = non_null(attrs.get('startIndex'), 0)
self.pageSize = non_null(attrs.get('pageSize'), 0)
self.totalCount = non_null(attrs.get('totalCount'), 0)
self.sortBy = attrs.get('sortBy')
self.sortType = attrs.get('sortType')
class SearchFilter(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.startIndex = non_null(attrs.get('startIndex'), 0)
self.maxsize = non_null(attrs.get('maxsize'), sys.maxsize)
self.getCount = non_null(attrs.get('getCount'), True)
#!/usr/bin/env/python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicabwle 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.
from apache_atlas.model.discovery import *
from apache_atlas.utils import *
class AtlasUserSavedSearch(AtlasBaseModelObject):
def __init__(self, attrs={}):
AtlasBaseModelObject.__init__(self, attrs)
self.ownerName = attrs.get('ownerName')
self.name = attrs.get('name')
self.searchType = attrs.get('searchType')
self.searchParameters = attrs.get('searchParameters')
self.uiParameters = attrs.get('uiParameters')
def type_coerce_attrs(self):
super(AtlasUserSavedSearch, self).type_coerce_attrs()
self.searchParameters = type_coerce(self.searchParameters, SearchParameters)
...@@ -17,41 +17,48 @@ ...@@ -17,41 +17,48 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import enum from apache_atlas.model.instance import *
from apache_atlas.utils import *
from apache_atlas.model.entity import AtlasStruct
class AtlasRelationship(AtlasStruct): class AtlasRelationship(AtlasStruct):
def __init__(self, attrs={}):
AtlasStruct.__init__(self, attrs)
self.guid = attrs.get('guid')
self.homeId = attrs.get('homeId')
self.provenanceType = attrs.get('provenanceType')
self.end1 = attrs.get('end1')
self.end2 = attrs.get('end2')
self.label = attrs.get('label')
self.propagateTags = attrs.get('propagateTags')
self.status = attrs.get('status')
self.createdBy = attrs.get('createdBy')
self.updatedBy = attrs.get('updatedBy')
self.createTime = attrs.get('createTime')
self.updateTime = attrs.get('updateTime')
self.version = attrs.get('version')
self.propagatedClassifications = attrs.get('propagatedClassifications')
self.blockedPropagatedClassifications = attrs.get('blockedPropagatedClassifications')
def type_coerce_attrs(self):
super(AtlasRelationship, self).type_coerce_attrs()
self.end1 = type_coerce(self.end1, AtlasObjectId)
self.end2 = type_coerce(self.end2, AtlasObjectId)
self.propagatedClassifications = type_coerce_list(self.propagatedClassifications, AtlasClassification)
self.blockedPropagatedClassifications = type_coerce_list(self.blockedPropagatedClassifications, AtlasClassification)
class AtlasRelationshipWithExtInfo(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.relationship = attrs.get('relationship')
self.referredEntities = attrs.get('referredEntities')
def type_coerce_attrs(self):
super(AtlasBase, self).type_coerce_attrs()
propagateTags_enum = enum.Enum('propagateTags_enum', 'NONE ONE_TO_TWO TWO_TO_ONE BOTH', module=__name__) self.relationship = type_coerce(self.relationship, AtlasRelationship)
status_enum = enum.Enum('status_enum', 'ACTIVE DELETED', module=__name__) self.referredEntities = type_coerce_dict(self.referredEntities, AtlasEntityHeader)
def __init__(self, typeName=None, attributes=None, guid=None, homeId=None, provenanceType=None, end1=None, end2=None,
label=None, propagateTags=None, status=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None,
version=0, propagatedClassifications=None, blockedPropagatedClassifications=None):
super().__init__(typeName, attributes)
self.guid = guid
self.homeId = homeId
self.provenanceType = provenanceType
self.end1 = end1
self.end2 = end2
self.label = label
self.propagateTags = propagateTags if propagateTags is not None else AtlasRelationship.propagateTags_enum.NONE.name
self.status = status if status is not None else AtlasRelationship.status_enum.ACTIVE.name
self.createdBy = createdBy
self.updatedBy = updatedBy
self.createTime = createTime
self.updateTime = updateTime
self.version = version
self.propagatedClassifications = propagatedClassifications if propagatedClassifications is not None else set()
self.blockedPropagatedClassifications = blockedPropagatedClassifications if blockedPropagatedClassifications is not None else set()
class AtlasRelationshipWithExtInfo:
def __init__(self, relationship=None, referredEntities=None):
self.relationship = relationship
self.referredEntities = referredEntities if referredEntities is not None else {}
...@@ -17,185 +17,179 @@ ...@@ -17,185 +17,179 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import enum import logging
from apache_atlas.model.enums import *
from apache_atlas.model.misc import *
from apache_atlas.utils import *
class AtlasTypesDef:
def __init__(self, enumDefs=None, structDefs=None, classificationDefs=None, LOG = logging.getLogger('apache_atlas')
entityDefs=None, relationshipDefs=None, businessMetadataDefs=None):
self.enumDefs = enumDefs if enumDefs is not None else []
self.structDefs = structDefs if structDefs is not None else []
self.classificationDefs = classificationDefs if classificationDefs is not None else []
self.entityDefs = entityDefs if entityDefs is not None else []
self.relationshipDefs = relationshipDefs if relationshipDefs is not None else []
self.businessMetadataDefs = businessMetadataDefs if businessMetadataDefs is not None else []
class AtlasBaseTypeDef: class AtlasBaseTypeDef(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
def __init__(self, category=None, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None, self.category = attrs.get('category')
version=None, name=None, description=None, typeVersion=None, serviceType=None, options=None): self.guid = attrs.get('guid')
self.category = category self.createdBy = attrs.get('createdBy')
self.guid = guid self.updatedBy = attrs.get('updatedBy')
self.createdBy = createdBy self.createTime = attrs.get('createTime')
self.updatedBy = updatedBy self.updateTime = attrs.get('updateTime')
self.createTime = createTime self.version = attrs.get('version')
self.updateTime = updateTime self.name = attrs.get('name')
self.version = version self.description = attrs.get('description')
self.name = name self.typeVersion = attrs.get('typeVersion')
self.description = description self.serviceType = attrs.get('serviceType')
self.typeVersion = typeVersion self.options = attrs.get('options')
self.serviceType = serviceType
self.options = options if options is not None else {}
category_enum = enum.Enum('category_enum', 'PRIMITIVE OBJECT_ID_TYPE ENUM STRUCT CLASSIFICATION ENTITY ARRAY MAP RELATIONSHIP BUSINESS_METADATA', module=__name__) class AtlasEnumDef(AtlasBaseTypeDef):
def __init__(self, attrs={}):
AtlasBaseTypeDef.__init__(self, attrs)
self.elementDefs = attrs.get('elementDefs')
self.defaultValue = attrs.get('defaultValue')
class AtlasEnumDef(AtlasBaseTypeDef): def type_coerce_attrs(self):
super(AtlasEnumDef, self).type_coerce_attrs()
def __init__(self, category=category_enum.ENUM.name, guid=None, createdBy=None, updatedBy=None, createTime=None, self.elementDefs = type_coerce_list(self.elementDefs, AtlasEnumElementDef)
updateTime=None, version=None, name=None, description=None, typeVersion=None,
serviceType=None, options=None, elementDefs=None, defaultValue=None):
super().__init__(category, guid, createdBy, updatedBy, createTime, updateTime, version, name, description, typeVersion, serviceType, options)
self.elementDefs = elementDefs if elementDefs is not None else [] class AtlasStructDef(AtlasBaseTypeDef):
self.defaultValue = defaultValue def __init__(self, attrs={}):
AtlasBaseTypeDef.__init__(self, attrs)
self.category = non_null(attrs.get('category'), TypeCategory.STRUCT.name)
self.attributeDefs = attrs.get('attributeDefs')
class AtlasEnumElementDef: def type_coerce_attrs(self):
super(AtlasStructDef, self).type_coerce_attrs()
def __init__(self, value=None, description=None, ordinal=None): self.attributeDefs = type_coerce_list(self.attributeDefs, AtlasAttributeDef)
self.value = value
self.description = description
self.ordinal = ordinal
class AtlasStructDef(AtlasBaseTypeDef): class AtlasClassificationDef(AtlasStructDef):
def __init__(self, attrs={}):
AtlasStructDef.__init__(self, attrs)
def __init__(self, category=category_enum.STRUCT.name, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None, version=None, self.category = TypeCategory.CLASSIFICATION.name
name=None, description=None, typeVersion=None, serviceType=None, options=None, attributeDefs=None): self.superTypes = attrs.get('superTypes')
self.entityTypes = attrs.get('entityTypes')
self.subTypes = attrs.get('subTypes')
super().__init__(category, guid, createdBy, updatedBy, createTime, updateTime, version, name, description, typeVersion, serviceType, options)
self.attributeDefs = attributeDefs if attributeDefs is not None else [] class AtlasEntityDef(AtlasStructDef):
def __init__(self, attrs={}):
AtlasStructDef.__init__(self, attrs)
self.category = TypeCategory.ENTITY.name
self.superTypes = attrs.get('superTypes')
self.subTypes = attrs.get('subTypes')
self.relationshipAttributeDefs = attrs.get('relationshipAttributeDefs')
self.businessAttributeDefs = attrs.get('businessAttributeDefs')
class AtlasAttributeDef: def type_coerce_attrs(self):
cardinality_enum = enum.Enum('cardinality_enum', 'SINGLE LIST SET', module=__name__) super(AtlasEntityDef, self).type_coerce_attrs()
indexType_enum = enum.Enum('indexType_enum', 'DEFAULT STRING', module=__name__)
def __init__(self, name=None, typeName=None, isOptional=None, cardinality=None, valuesMinCount=None, valuesMaxCount=None, self.relationshipAttributeDefs = type_coerce_list(self.relationshipAttributeDefs, AtlasRelationshipAttributeDef)
isUnique=None, isIndexable=None, includeInNotification=None, defaultValue=None, description=None, searchWeight= -1, self.businessAttributeDefs = type_coerce_dict_list(self.businessAttributeDefs, AtlasAttributeDef)
indexType=None, constraints=None, options=None, displayName=None):
self.name = name
self.typeName = typeName
self.isOptional = isOptional
self.cardinality = cardinality
self.valuesMinCount = valuesMinCount
self.valuesMaxCount = valuesMaxCount
self.isUnique = isUnique
self.isIndexable = isIndexable
self.includeInNotification = includeInNotification
self.defaultValue = defaultValue
self.description = description
self.searchWeight = searchWeight
self.indexType = indexType
self.constraints = constraints if constraints is not None else []
self.options = options if options is not None else {}
self.displayName = displayName
class AtlasRelationshipDef(AtlasStructDef):
def __init__(self, attrs={}):
AtlasStructDef.__init__(self, attrs)
class AtlasConstraintDef: self.category = TypeCategory.RELATIONSHIP.name
def __init__(self, type=None, params=None):
self.type = type
self.params = params if params is not None else {}
class AtlasBusinessMetadataDef(AtlasStructDef):
def __init__(self, attrs={}):
AtlasStructDef.__init__(self, attrs)
class AtlasClassificationDef(AtlasStructDef): self.category = TypeCategory.BUSINESS_METADATA.name
def __init__(self, category=category_enum.CLASSIFICATION.name, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None,
version=None, name=None, description=None, typeVersion=None, serviceType=None, options=None,
attributeDefs=None, superTypes=None, entityTypes=None, subTypes=None):
super().__init__(category, guid, createdBy, updatedBy, createTime, updateTime, version, class AtlasAttributeDef(AtlasBase):
name, description, typeVersion, serviceType, options, attributeDefs) def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.superTypes = superTypes if superTypes is not None else set() self.name = attrs.get('name')
self.entityTypes = entityTypes if entityTypes is not None else set() self.typeName = attrs.get('typeName')
self.subTypes = subTypes if subTypes is not None else set() self.isOptional = attrs.get('isOptional')
self.cardinality = attrs.get('cardinality')
self.valuesMinCount = attrs.get('valuesMinCount')
self.valuesMaxCount = attrs.get('valuesMaxCount')
self.isUnique = attrs.get('isUnique')
self.isIndexable = attrs.get('isIndexable')
self.includeInNotification = attrs.get('includeInNotification')
self.defaultValue = attrs.get('defaultValue')
self.description = attrs.get('description')
self.searchWeight = non_null(attrs.get('searchWeight'), -1)
self.indexType = attrs.get('indexType')
self.constraints = attrs.get('constraints')
self.options = attrs.get('options')
self.displayName = attrs.get('displayName')
def type_coerce_attrs(self):
super(AtlasAttributeDef, self).type_coerce_attrs()
self.constraints = type_coerce_list(self.constraints, AtlasConstraintDef)
class AtlasConstraintDef(AtlasBase):
def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.type = attrs.get('type')
self.params = attrs.get('params')
class AtlasEntityDef(AtlasStructDef):
def __init__(self, category=category_enum.CLASSIFICATION.name, guid=None, createdBy=None, updatedBy=None, createTime=None, updateTime=None,
version=None, name=None, description=None, typeVersion=None, serviceType=None, options=None,
attributeDefs=None, superTypes=None, subTypes=None, relationshipAttributeDefs=None, businessAttributeDefs=None):
super().__init__(category, guid, createdBy, updatedBy, createTime, updateTime, version, class AtlasEnumElementDef(AtlasBase):
name, description, typeVersion, serviceType, options, attributeDefs) def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.superTypes = superTypes if superTypes is not None else set() self.value = attrs.get('value')
self.subTypes = subTypes if subTypes is not None else set() self.description = attrs.get('description')
self.relationshipAttributeDefs = relationshipAttributeDefs if relationshipAttributeDefs is not None else [] self.ordinal = attrs.get('ordinal')
self.businessAttributeDefs = businessAttributeDefs if businessAttributeDefs is not None else {}
class AtlasRelationshipAttributeDef(AtlasAttributeDef): class AtlasRelationshipAttributeDef(AtlasAttributeDef):
cardinality_enum = enum.Enum('cardinality_enum', 'SINGLE LIST SET', module=__name__) def __init__(self, attrs={}):
indexType_enum = enum.Enum('indexType_enum', 'DEFAULT STRING', module=__name__) AtlasAttributeDef.__init__(self, attrs)
def __init__(self, name=None, typeName=None, isOptional=None, cardinality=None, valuesMinCount=None, self.relationshipTypeName = attrs.get('relationshipTypeName')
valuesMaxCount=None, isUnique=None, isIndexable=None, includeInNotification=None, self.isLegacyAttribute = attrs.get('isLegacyAttribute')
defaultValue=None, description=None, searchWeight=None, indexType=None, constraints=None,
options=None, displayName=None, relationshipTypeName=None, isLegacyAttribute=None):
super().__init__(name, typeName, isOptional, cardinality, valuesMinCount, valuesMaxCount, isUnique, isIndexable,
includeInNotification, defaultValue, description, searchWeight, indexType, constraints, options, displayName)
self.relationshipTypeName = relationshipTypeName class AtlasRelationshipEndDef(AtlasBase):
self.isLegacyAttribute = isLegacyAttribute def __init__(self, attrs={}):
AtlasBase.__init__(self, attrs)
self.cardinality = non_null(self.cardinality, Cardinality.SINGLE.name)
class AtlasBusinessMetadataDef(AtlasStructDef):
def __init__(self, category=category_enum.BUSINESS_METADATA.name, guid=None, createdBy=None, updatedBy=None, createTime=None, class AtlasTypesDef(AtlasBase):
updateTime=None, version=None, name=None, description=None, typeVersion=None, def __init__(self, attrs={}):
serviceType=None, options=None, attributeDefs=None): AtlasBase.__init__(self, attrs)
super().__init__(category, guid, createdBy, updatedBy, createTime, updateTime, version, self.enumDefs = attrs.get('enumDefs')
name, description, typeVersion, serviceType, options, attributeDefs) self.structDefs = attrs.get('structDefs')
self.classificationDefs = attrs.get('classificationDefs')
self.entityDefs = attrs.get('entityDefs')
self.relationshipDefs = attrs.get('relationshipDefs')
self.businessMetadataDefs = attrs.get('businessMetadataDefs')
def type_coerce_attrs(self):
super(AtlasTypesDef, self).type_coerce_attrs()
self.enumDefs = type_coerce_list(self.enumDefs, AtlasEnumDef)
self.structDefs = type_coerce_list(self.structDefs, AtlasStructDef)
self.classificationDefs = type_coerce_list(self.classificationDefs, AtlasClassificationDef)
self.entityDefs = type_coerce_list(self.entityDefs, AtlasEntityDef)
self.relationshipDefs = type_coerce_list(self.relationshipDefs, AtlasRelationshipDef)
self.businessMetadataDefs = type_coerce_list(self.businessMetadataDefs, AtlasBusinessMetadataDef)
class AtlasRelationshipDef(AtlasStructDef):
relationshipCategory_enum = enum.Enum('relationshipCategory_enum', 'ASSOCIATION AGGREGATION COMPOSITION', module=__name__)
propagateTags_enum = enum.Enum('propagateTags_enum', 'NONE ONE_TO_TWO TWO_TO_ONE BOTH', module=__name__)
def __init__(self, category=category_enum.RELATIONSHIP.name, guid=None, createdBy=None, updatedBy=None, createTime=None,
updateTime=None, version=None, name=None, description=None, typeVersion=None,
serviceType=None, options=None, attributeDefs=None, relationshipCategory=None,
relationshipLabel=None, propagateTags=None, endDef1=None, endDef2=None):
super().__init__(category, guid, createdBy, updatedBy, createTime, updateTime, version,
name, description, typeVersion, serviceType, options, attributeDefs)
self.relationshipCategory = relationshipCategory
self.relationshipLabel = relationshipLabel
self.propagateTags = propagateTags
self.endDef1 = endDef1
self.endDef2 = endDef2
class AtlasRelationshipEndDef:
cardinality_enum = enum.Enum('cardinality_enum', 'SINGLE LIST SET', module=__name__)
def __init__(self, type=None, name=None, isContainer=None, cardinality=None, isLegacyAttribute=None, description=None):
self.type = type
self.name = name
self.isContainer = isContainer
self.cardinality = cardinality if cardinality is not None else AtlasRelationshipEndDef.cardinality_enum.SINGLE.name
self.isLegacyAttribute = isLegacyAttribute
self.description = description
\ No newline at end of file
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
# limitations under the License. # limitations under the License.
import enum import enum
from json import JSONEncoder
import time import time
BASE_URI = "api/atlas/" BASE_URI = "api/atlas/"
...@@ -30,6 +29,12 @@ PREFIX_ATTR_ = "attr_" ...@@ -30,6 +29,12 @@ PREFIX_ATTR_ = "attr_"
s_nextId = milliseconds = int(round(time.time() * 1000)) + 1 s_nextId = milliseconds = int(round(time.time() * 1000)) + 1
def next_id():
global s_nextId
s_nextId += 1
return "-" + str(s_nextId)
def list_attributes_to_params(attributes_list, query_params=None): def list_attributes_to_params(attributes_list, query_params=None):
if not query_params: if not query_params:
...@@ -42,7 +47,6 @@ def list_attributes_to_params(attributes_list, query_params=None): ...@@ -42,7 +47,6 @@ def list_attributes_to_params(attributes_list, query_params=None):
return query_params return query_params
def attributes_to_params(attributes, query_params=None): def attributes_to_params(attributes, query_params=None):
if not query_params: if not query_params:
query_params = {} query_params = {}
...@@ -54,12 +58,50 @@ def attributes_to_params(attributes, query_params=None): ...@@ -54,12 +58,50 @@ def attributes_to_params(attributes, query_params=None):
return query_params return query_params
def non_null(obj, defValue):
return obj if obj is not None else defValue
class HttpMethod(enum.Enum): def type_coerce(obj, objType):
GET = "GET" if isinstance(obj, objType):
PUT = "PUT" ret = obj
POST = "POST" elif isinstance(obj, dict):
DELETE = "DELETE" ret = objType(obj)
ret.type_coerce_attrs()
else:
ret = None
return ret
def type_coerce_list(obj, objType):
if isinstance(obj, list):
ret = []
for entry in obj:
ret.append(type_coerce(entry, objType))
else:
ret = None
return ret
def type_coerce_dict(obj, objType):
if isinstance(obj, dict):
ret = {}
for k, v in obj.items():
ret[k] = type_coerce(v, objType)
else:
ret = None
return ret
def type_coerce_dict_list(obj, objType):
if isinstance(obj, dict):
ret = {}
for k, v in obj.items():
ret[k] = type_coerce_list(v, objType)
else:
ret = None
return ret
class API: class API:
...@@ -71,7 +113,7 @@ class API: ...@@ -71,7 +113,7 @@ class API:
self.produces = produces self.produces = produces
def format_path(self, params): def format_path(self, params):
return API(self.path.format_map(params), self.method, self.expected_status, self.consumes, self.produces) return API(self.path.format(**params), self.method, self.expected_status, self.consumes, self.produces)
def format_path_with_params(self, *params): def format_path_with_params(self, *params):
path = self.path path = self.path
...@@ -82,14 +124,14 @@ class API: ...@@ -82,14 +124,14 @@ class API:
return API(path, self.method, self.expected_status, self.consumes, self.produces) return API(path, self.method, self.expected_status, self.consumes, self.produces)
class CustomEncoder(JSONEncoder): class HttpMethod(enum.Enum):
def default(self, o): GET = "GET"
if isinstance(o, set): PUT = "PUT"
return list(o) POST = "POST"
DELETE = "DELETE"
return o.__dict__
class AtlasBaseModelObject: class HTTPStatus:
def __init__(self, guid=None): OK = 200
self.guid = guid if guid is not None else "-" + str(s_nextId) NO_CONTENT = 204
\ No newline at end of file SERVICE_UNAVAILABLE = 503
...@@ -22,18 +22,22 @@ from setuptools import setup, find_packages ...@@ -22,18 +22,22 @@ from setuptools import setup, find_packages
# External dependencies # External dependencies
requirements = ['requests>=2.24'] requirements = ['requests>=2.24']
long_description = ''
with open("README.md", "r") as fh:
long_description = fh.read()
setup( setup(
name='apache-atlas', name='apache-atlas',
version='0.0.1', version='0.0.2',
author="Apache Atlas", author="Apache Atlas",
author_email='dev@atlas.apache.org', author_email='dev@atlas.apache.org',
description="Apache Atlas Python Client", description="Apache Atlas Python Client",
long_description="Apache Atlas Python client", long_description=long_description,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
url="https://github.com/apache/atlas/tree/master/intg/src/main/python", url="https://github.com/apache/atlas/tree/master/intg/src/main/python",
license='Apache LICENSE 2.0', license='Apache LICENSE 2.0',
classifiers=[ classifiers=[
"Programming Language :: Python :: 3", "Programming Language :: Python :: 2.7",
"License :: OSI Approved :: Apache Software License", "License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent", "Operating System :: OS Independent",
], ],
...@@ -42,4 +46,5 @@ setup( ...@@ -42,4 +46,5 @@ setup(
include_package_data=True, include_package_data=True,
zip_safe=False, zip_safe=False,
keywords='atlas client, apache atlas', keywords='atlas client, apache atlas',
python_requires='>=2.7',
) )
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment