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)
if self.entity_table_us: self.entity_table_us = self.__create_table_helper(entity)
LOG.info("Created table entity for US: %s", self.entity_table_us['typeName'])
else: if self.entity_table_us:
LOG.info("Table entity for US not created") LOG.info("Created US table entity: guid=%s, attr.name=%s", self.entity_table_us.guid, self.entity_table_us.attributes['name'])
else:
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)
if self.entity_table_canada: self.entity_table_canada = self.__create_table_helper(entity)
LOG.info("Created table entity for Canada: %s", self.entity_table_canada['typeName'])
else:
LOG.info("Table entity for Canada not created")
def __create_table_helper(self, ext_info): if self.entity_table_canada:
instance_entity = ext_info['entity'] LOG.info("Created Canada table entity: guid=%s, attr.name=%s", self.entity_table_canada.guid, self.entity_table_canada.attributes['name'])
else:
LOG.info("Failed to create Canada table entity")
if self.db_entity: def __create_process(self):
instance_entity['relationshipAttributes']['db']['guid'] = self.db_entity['guid'] if not self.entity_process:
instance_entity['relationshipAttributes']['db']['typeName'] = self.db_entity['typeName'] with open('request_json/entity_create_process.json') as f:
entity = type_coerce(json.load(f), AtlasEntityWithExtInfo)
ext_info['entity'] = instance_entity self.entity_process = self.__create_process_helper(entity)
entity = self.__create_entity(ext_info) 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")
if entity and entity['guid']: def __create_db_helper(self, entity):
instance_entity['guid'] = entity['guid'] self.__create_entity(entity)
return instance_entity return entity.entity
def __create_process(self): def __create_table_helper(self, entity):
if not self.load_process: table = entity.entity
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: if self.entity_db:
LOG.info("Created process Entity: %s", self.load_process['typeName']) dbId = AtlasRelatedObjectId({ 'guid': self.entity_db.guid })
else:
LOG.info("Process Entity not created")
def __create_process_helper(self, ext_info): LOG.info("setting: table(%s).db=%s", table.guid, dbId)
instance_entity = ext_info['entity']
if self.entity_table_us: table.relationshipAttributes['db'] = dbId
input_list = []
input_data = {'guid': self.entity_table_us['guid'],
'typeName': self.entity_table_us['typeName']
}
input_list.append(input_data) self.__create_entity(entity)
instance_entity['relationshipAttributes']['inputs'] = input_list return table
if self.entity_table_canada: def __create_process_helper(self, entity):
output_list = [] process = entity.entity
output_data = {'guid': self.entity_table_canada['guid'],
'typeName': self.entity_table_canada['typeName']
}
output_list.append(output_data) process.relationshipAttributes = {}
instance_entity['relationshipAttributes']['outputs'] = output_list if self.entity_table_us:
process.relationshipAttributes['inputs'] = [ AtlasRelatedObjectId({ 'guid': self.entity_table_us.guid }) ]
ext_info['entity'] = instance_entity if self.entity_table_canada:
process.relationshipAttributes['outputs'] = [ AtlasRelatedObjectId({'guid': self.entity_table_canada.guid }) ]
return self.__create_entity(ext_info) return self.__create_entity(entity)
def __create_entity(self, ext_info): def __create_entity(self, entity):
try: try:
entity = self.client.entity.create_entity(ext_info) response = self.client.entity.create_entity(entity)
create_enum = EntityMutations.entity_operation_enum.CREATE.name
guid = None
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]
if header_list and len(header_list) > 0:
guid = header_list[0].guid
elif response and response.guidAssignments:
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", "description": "employee database",
"qualifiedName": "employee_db_entity@cl1", "owner": "user",
"name": "employee_db_entity", "clusterName": "cl1",
"description": "employee database", "locationUri": "/hive/database/employee_db",
"locationUri": "/tmp" "createTime": 1607476058882
}, }
"guid": "-222736766326565",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"proxy": false
} }
} }
\ No newline at end of file
{ {
"entity": { "entity": {
"typeName": "sample_process_type", "typeName": "sample_process",
"attributes": { "attributes": {
"queryGraph": "graph", "name": "employee_process",
"qualifiedName": "employee_process_entity@cl1", "description": "hive query for monthly avg salary",
"name": "employee_process_entity", "qualifiedName": "employee_process@cl1",
"queryText": "create table as select ", "userName": "user ETL",
"description": "hive query for monthly avg salary", "startTime": 1607476549507,
"startTime": 1596855233685, "endTime": 1607476552529,
"queryPlan": "plan", "queryText": "create table as select ",
"operationType": "testOperation", "queryId": "<query-id>"
"endTime": 1596855243685,
"userName": "user ETL",
"queryId": "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
} }
} }
\ No newline at end of file
{ {
"entity": {
"guid": "-1",
"typeName": "sample_table",
"attributes": {
"name": "employees_canada",
"description": "Canada employees",
"qualifiedName": "employee_db.employees_canada@cl1",
"tableType": "Managed",
"serde1": { "typeName": "sample_serdeType", "attributes": { "name": "serde1", "serde": "serde1" } },
"serde2": { "typeName": "sample_serdeType", "attributes": { "name": "serde2", "serde": "serde2" } }
},
"relationshipAttributes": {
"db": { "typeName": "sample_db", "uniqueAttributes": { "qualifiedName": "employee_db@cl1" } },
"columns": [
{ "guid": "-2" },
{ "guid": "-3" },
{ "guid": "-4" }
]
}
},
"referredEntities": { "referredEntities": {
"-222736766326566": { "-2": {
"typeName": "sample_column_type", "guid": "-2",
"typeName": "sample_column",
"attributes": { "attributes": {
"qualifiedName": "time_id@cl1", "table": { "guid": "-1" },
"dataType": "int", "name": "time_id",
"name": "time_id", "dataType": "int",
"comment": "time id" "comment": "time id",
}, "qualifiedName": "employee_db.employees_canada.time_id@cl1"
"guid": "-222736766326566", }
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326569",
"typeName": "sample_table_type"
}
},
"classifications": [],
"proxy": false
}, },
"-222736766326567": { "-3": {
"typeName": "sample_column_type", "guid": "-3",
"typeName": "sample_column",
"attributes": { "attributes": {
"qualifiedName": "customer_id@cl1", "table": { "guid": "-1" },
"dataType": "int", "name": "customer_id",
"name": "customer_id", "dataType": "int",
"comment": "customer id" "comment": "customer id",
}, "qualifiedName": "employee_db.employees_canada.customer_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": { "-4": {
"typeName": "sample_column_type", "guid": "-4",
"typeName": "sample_column",
"attributes": { "attributes": {
"qualifiedName": "company_id@cl1", "table": { "guid": "-1" },
"dataType": "double", "name": "company_id",
"name": "company_id", "dataType": "double",
"comment": "company id" "comment": "company id",
}, "qualifiedName": "employee_db.employees_canada.company_id@cl1"
"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": {
"typeName": "sample_table_type",
"attributes": {
"serde2": {
"typeName": "serdeType",
"attributes": {
"serde": "serde2",
"name": "serde2"
}
},
"tableType": "Managed",
"serde1": {
"typeName": "serdeType",
"attributes": {
"serde": "serde1",
"name": "serde1"
}
},
"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
} }
} }
\ No newline at end of file
{ {
"entity": {
"guid": "-1",
"typeName": "sample_table",
"attributes": {
"name": "employees_us",
"description": "US employees",
"qualifiedName": "employee_db.employees_us@cl1",
"tableType": "Managed",
"serde1": { "typeName": "sample_serdeType", "attributes": { "name": "serde1", "serde": "serde1" } },
"serde2": { "typeName": "sample_serdeType", "attributes": { "name": "serde2", "serde": "serde2" } }
},
"relationshipAttributes": {
"db": { "typeName": "sample_db", "uniqueAttributes": { "qualifiedName": "employee_db@cl1" } },
"columns": [
{ "guid": "-2" },
{ "guid": "-3" },
{ "guid": "-4" }
]
}
},
"referredEntities": { "referredEntities": {
"-222736766326570": { "-2": {
"typeName": "sample_column_type", "guid": "-2",
"typeName": "sample_column",
"attributes": { "attributes": {
"qualifiedName": "time_id@cl1", "name": "time_id",
"dataType": "int", "dataType": "int",
"name": "time_id", "comment": "time id",
"comment": "time id" "qualifiedName": "employee_db.employees_us.time_id@cl1",
}, "table": { "guid": "-1" }
"guid": "-222736766326570", }
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326573",
"typeName": "sample_table_type"
}
},
"classifications": [],
"proxy": false
}, },
"-222736766326571": { "-3": {
"typeName": "sample_column_type", "guid": "-3",
"typeName": "sample_column",
"attributes": { "attributes": {
"qualifiedName": "customer_id@cl1",
"dataType": "int",
"name": "customer_id", "name": "customer_id",
"comment": "customer id" "dataType": "int",
}, "comment": "customer id",
"guid": "-222736766326571", "qualifiedName": "employee_db.employees_us.customer_id@cl1",
"isIncomplete": false, "table": { "guid": "-1" }
"provenanceType": 0, }
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326573",
"typeName": "sample_table_type"
}
},
"classifications": [{
"typeName": "sample_pii_Tag",
"entityStatus": "ACTIVE"
}],
"proxy": false
}, },
"-222736766326572": { "-4": {
"typeName": "sample_column_type", "guid": "-4",
"typeName": "sample_column",
"attributes": { "attributes": {
"qualifiedName": "company_id@cl1", "name": "company_id",
"dataType": "double", "dataType": "double",
"name": "company_id", "comment": "company id",
"comment": "company id" "qualifiedName": "employee_db.employees_us.company_id@cl1",
}, "table": { "guid": "-1" }
"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": {
"typeName": "sample_table_type",
"attributes": {
"serde2": {
"typeName": "serdeType",
"attributes": {
"serde": "serde2",
"name": "serde2"
}
},
"tableType": "Managed",
"serde1": {
"typeName": "serdeType",
"attributes": {
"serde": "serde1",
"name": "serde1"
}
},
"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
} }
} }
\ No newline at end of file
{ {
"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
} }
} }
] ]
} }
] ]
} }
\ No newline at end of file
...@@ -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 import logging
import getpass
from apache_atlas.base_client import AtlasClient from apache_atlas.client.base_client import AtlasClient
from typedef_example import TypeDefExample
from entity_example import EntityExample
from lineage_example import LineageExample
from glossary_example import GlossaryExample
from discovery_example import DiscoveryExample
from utils import METRIC_CLASSIFICATION, NAME
from typedef_example import TypeDefExample
from entity_example import EntityExample
from lineage_example import LineageExample
from glossary_example import GlossaryExample
from discovery_example import DiscoveryExample
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,10 +101,30 @@ class SampleApp: ...@@ -108,10 +101,30 @@ 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__":
SampleApp().main() SampleApp().main()
\ No newline at end of file
...@@ -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,52 +65,58 @@ class TypeDefExample: ...@@ -63,52 +65,58 @@ 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)
self.typesDef = None self.typesDef = None
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)
\ No newline at end of file
...@@ -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 requests import Session
from apache_atlas.utils import CustomEncoder, HttpMethod from apache_atlas.client.discovery import DiscoveryClient
from apache_atlas.client.typedef import TypeDefClient from apache_atlas.client.entity import EntityClient
from apache_atlas.client.discovery import DiscoveryClient from apache_atlas.client.glossary import GlossaryClient
from apache_atlas.client.entity import EntityClient from apache_atlas.client.lineage import LineageClient
from apache_atlas.client.glossary import GlossaryClient
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.utils import HttpMethod, HTTPStatus, type_coerce
from apache_atlas.exceptions import AtlasServiceException
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)
\ No newline at end of file
...@@ -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',
\ No newline at end of file )
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