Commit 5aab626e by jyoti0208 Committed by Sarath Subramanian

ATLAS-3875: Introduce python client for Atlas

parent 74c93941
......@@ -47,6 +47,10 @@ test-output
#Python
*.pyc
**/build
**/dist
**/apache_atlas.egg-info
.python-version
# review board
.reviewboardrc
......
......@@ -51,7 +51,7 @@ public class GlossaryExample {
assert (extInfo != null);
SampleApp.log("extra info of Glossary is :- " + extInfo.getGuid() + " name is :- " + extInfo.getName() + " language is :- " + extInfo.getLanguage());
SampleApp.log("Glossary extended info: " + extInfo.getGuid() + "; name: " + extInfo.getName() + "; language: " + extInfo.getLanguage());
}
public void createGlossaryTerm() throws Exception {
......
# Python Sample App
This is a Python sample app to showcase basic functionality of Atlas. We are using Python client
to call Atlas APIs. Make sure to install Atlas Python client first before trying to run this project. Currently, compatible with Python 3.5+
## Installation
1. Using `setup.py`
```bash
cd <atlas_directory>/atlas-examples/sample-app/src/main/python
# To check if apache-atlas client is installed try the following command
python3
>>> import apache_atlas
>>>
# If there is no error, then client is installed otherwise follow client Readme file to install it first.
```
To Run this project
```bash
python sample_client.py
```
This will prompt for url of the Atlas server, username and password.
#!/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 logging
from utils import TABLE_TYPE
LOG = logging.getLogger('discovery-example')
class DiscoveryExample:
DSL_QUERIES = {"from DataSet", "from Process"}
def __init__(self, client):
self.typesDef = None
self.client = client
def dsl_search(self):
for dsl_query in DiscoveryExample.DSL_QUERIES:
try:
result = self.client.discovery.dsl_search_with_params(dsl_query, 10, 0)
if result:
entities_result = result.entities
if entities_result:
LOG.info("query: '%s' retrieved: %s rows", dsl_query, len(entities_result))
except Exception as e:
LOG.exception("query: %s failed in dsl search", dsl_query)
def quick_search(self, search_string):
try:
result = self.client.discovery.quick_search(search_string, TABLE_TYPE, False, 2, 0)
if result:
LOG.info("Quick-search result: %s", result.searchResults)
except Exception as e:
LOG.exception("query: '%s' failed in quick search", search_string)
def basic_search(self, type_name, classification, query):
try:
result = self.client.discovery.basic_search(type_name, classification, query, False, 2, 0)
if result:
LOG.info("Basic-search result: %s", result)
except Exception as e:
LOG.exception("query: '%s' failed in basic search", query)
\ 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 json
import logging
from apache_atlas.model.entity import AtlasEntityWithExtInfo, EntityMutations
LOG = logging.getLogger('entity-example')
class EntityExample:
DATABASE_NAME = "employee_db_entity"
TABLE_NAME = "employee_table_entity"
PROCESS_NAME = "employee_process_entity"
METADATA_NAMESPACE_SUFFIX = "@cl1"
MANAGED_TABLE = "Managed"
ATTR_NAME = "name"
ATTR_DESCRIPTION = "description"
ATTR_QUALIFIED_NAME = "qualifiedName"
REFERENCEABLE_ATTRIBUTE_NAME = ATTR_QUALIFIED_NAME
ATTR_TIME_ID_COLUMN = "time_id"
ATTR_CUSTOMER_ID_COLUMN = "customer_id"
ATTR_COMPANY_ID_COLUMN = "company_id"
def __init__(self, client):
self.client = client
self.db_entity = None
self.entity_table_us = None
self.entity_table_canada = None
self.load_process = None
def create_entities(self):
self.__create_db()
self.__create_us_table()
self.__create_canada_table()
self.__create_process()
def get_table_entity(self):
if self.entity_table_us:
return self.entity_table_us
return None
def get_entity_by_guid(self, entity_guid):
entity_with_ext_info = self.client.entity.get_entity_by_guid(entity_guid)
if entity_with_ext_info:
LOG.info("Entity info is : %s", entity_with_ext_info)
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']]
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.db_entity['typeName'],
self.entity_table_us['typeName'],
self.entity_table_canada['typeName'],
self.load_process['typeName'])
def __create_db(self):
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:
LOG.info("Created database entity: %s", self.db_entity['typeName'])
else:
LOG.info("Database entity not created")
def __create_db_helper(self, ext_info):
instance_entity = ext_info['entity']
entity = self.__create_entity(ext_info)
if entity and entity['guid']:
instance_entity['guid'] = entity['guid']
return instance_entity
def __create_us_table(self):
if not self.entity_table_us:
with open('request_json/entity_create_table_us.json') as f:
entity_table_us = json.load(f)
self.entity_table_us = self.__create_table_helper(entity_table_us)
if self.entity_table_us:
LOG.info("Created table entity for US: %s", self.entity_table_us['typeName'])
else:
LOG.info("Table entity for US not created")
def __create_canada_table(self):
if not self.entity_table_canada:
with open('request_json/entity_create_table_canada.json') as f:
entity_table_canada = json.load(f)
self.entity_table_canada = self.__create_table_helper(entity_table_canada)
if self.entity_table_canada:
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):
instance_entity = ext_info['entity']
if self.db_entity:
instance_entity['relationshipAttributes']['db']['guid'] = self.db_entity['guid']
instance_entity['relationshipAttributes']['db']['typeName'] = self.db_entity['typeName']
ext_info['entity'] = instance_entity
entity = self.__create_entity(ext_info)
if entity and entity['guid']:
instance_entity['guid'] = entity['guid']
return instance_entity
def __create_process(self):
if not self.load_process:
with open('request_json/entity_create_process.json') as f:
entity_process = json.load(f)
self.load_process = self.__create_process_helper(entity_process)
if self.load_process:
LOG.info("Created process Entity: %s", self.load_process['typeName'])
else:
LOG.info("Process Entity not created")
def __create_process_helper(self, ext_info):
instance_entity = ext_info['entity']
if self.entity_table_us:
input_list = []
input_data = {'guid': self.entity_table_us['guid'],
'typeName': self.entity_table_us['typeName']
}
input_list.append(input_data)
instance_entity['relationshipAttributes']['inputs'] = input_list
if self.entity_table_canada:
output_list = []
output_data = {'guid': self.entity_table_canada['guid'],
'typeName': self.entity_table_canada['typeName']
}
output_list.append(output_data)
instance_entity['relationshipAttributes']['outputs'] = output_list
ext_info['entity'] = instance_entity
return self.__create_entity(ext_info)
def __create_entity(self, ext_info):
try:
entity = self.client.entity.create_entity(ext_info)
create_enum = EntityMutations.entity_operation_enum.CREATE.name
if entity and entity.mutatedEntities and entity.mutatedEntities[create_enum]:
header_list = entity.mutatedEntities[create_enum]
if len(header_list) > 0:
return header_list[0]
except Exception as e:
LOG.exception("failed to create entity %s", ext_info['entity'])
return None
\ 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 logging
from apache_atlas.model.glossary import AtlasGlossary, AtlasGlossaryCategory, AtlasGlossaryTerm, AtlasGlossaryHeader
LOG = logging.getLogger('glossary-example')
class GlossaryExample:
glossaryName = "EmployeeCountry"
def __init__(self, client):
self.client = client
self.emp_glossary = None
self.emp_salary_term = None
self.emp_company_category = None
def create_glossary(self):
glossary = AtlasGlossary(None, None, GlossaryExample.glossaryName, "This is a test 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)
return self.emp_glossary
def get_glossary_detail(self):
ext_info = self.client.glossary.get_glossary_ext_info(self.emp_glossary.guid)
if ext_info:
LOG.info("Glossary extended info: %s; name: %s; language: %s", ext_info.guid, ext_info.name, ext_info.language)
def create_glossary_term(self):
header = AtlasGlossaryHeader(self.emp_glossary.guid, None, self.emp_glossary.name)
term = AtlasGlossaryTerm(None, None, "EmpSalaryTerm", None, None, None, None, None, None, None, header)
self.emp_salary_term = self.client.glossary.create_glossary_term(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)
def create_glossary_category(self):
header = AtlasGlossaryHeader(self.emp_glossary.guid, None, self.emp_glossary.name)
category = AtlasGlossaryCategory(None, None, "EmpSalaryCategory", None, None, None, None, header)
self.emp_company_category = self.client.glossary.create_glossary_category(category)
if self.emp_company_category:
LOG.info("Created Category for Employee Category: %s with guid: %s", self.emp_company_category.name, self.emp_company_category.guid)
def delete_glossary(self):
if not self.emp_glossary:
LOG.info("empGlossary is not present. Skipping the delete operation.")
self.client.glossary.delete_glossary_by_guid(self.emp_glossary.guid)
LOG.info("Delete is complete for Glossary!")
\ 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 logging
from apache_atlas.model.lineage import AtlasLineageInfo
LOG = logging.getLogger('lineage-example')
class LineageExample:
def __init__(self, client):
self.client = client
def lineage(self, guid):
direction = AtlasLineageInfo.lineageDirection_enum.BOTH.name
lineage_info = self.client.lineage.get_lineage_info(guid, direction, 0)
if not lineage_info:
LOG.info("Not able to find lineage info")
return
relations = lineage_info.relations
guid_entity_map = lineage_info.guidEntityMap
for relation in relations:
from_entity = guid_entity_map[relation['fromEntityId']]
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'])
\ No newline at end of file
{
"entity": {
"typeName": "sample_db_type",
"attributes": {
"owner": "user",
"createTime": 1000,
"@cl1": "employeeCluster",
"qualifiedName": "employee_db_entity@cl1",
"name": "employee_db_entity",
"description": "employee database",
"locationUri": "/tmp"
},
"guid": "-222736766326565",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"proxy": false
}
}
\ No newline at end of file
{
"entity": {
"typeName": "sample_process_type",
"attributes": {
"queryGraph": "graph",
"qualifiedName": "employee_process_entity@cl1",
"name": "employee_process_entity",
"queryText": "create table as select ",
"description": "hive query for monthly avg salary",
"startTime": 1596855233685,
"queryPlan": "plan",
"operationType": "testOperation",
"endTime": 1596855243685,
"userName": "user ETL",
"queryId": "id"
},
"guid": "-222736766326574",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"outputs": [{
"guid": "b0619fb9-b025-4348-8b8a-79e8faa0e789",
"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
{
"referredEntities": {
"-222736766326566": {
"typeName": "sample_column_type",
"attributes": {
"qualifiedName": "time_id@cl1",
"dataType": "int",
"name": "time_id",
"comment": "time id"
},
"guid": "-222736766326566",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326569",
"typeName": "sample_table_type"
}
},
"classifications": [],
"proxy": false
},
"-222736766326567": {
"typeName": "sample_column_type",
"attributes": {
"qualifiedName": "customer_id@cl1",
"dataType": "int",
"name": "customer_id",
"comment": "customer id"
},
"guid": "-222736766326567",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326569",
"typeName": "sample_table_type"
}
},
"classifications": [{
"typeName": "sample_pii_Tag",
"entityStatus": "ACTIVE"
}],
"proxy": false
},
"-222736766326568": {
"typeName": "sample_column_type",
"attributes": {
"qualifiedName": "company_id@cl1",
"dataType": "double",
"name": "company_id",
"comment": "company id"
},
"guid": "-222736766326568",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326569",
"typeName": "sample_table_type"
}
},
"classifications": [{
"typeName": "sample_finance_Tag",
"entityStatus": "ACTIVE"
}],
"proxy": false
}
},
"entity": {
"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
{
"referredEntities": {
"-222736766326570": {
"typeName": "sample_column_type",
"attributes": {
"qualifiedName": "time_id@cl1",
"dataType": "int",
"name": "time_id",
"comment": "time id"
},
"guid": "-222736766326570",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326573",
"typeName": "sample_table_type"
}
},
"classifications": [],
"proxy": false
},
"-222736766326571": {
"typeName": "sample_column_type",
"attributes": {
"qualifiedName": "customer_id@cl1",
"dataType": "int",
"name": "customer_id",
"comment": "customer id"
},
"guid": "-222736766326571",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326573",
"typeName": "sample_table_type"
}
},
"classifications": [{
"typeName": "sample_pii_Tag",
"entityStatus": "ACTIVE"
}],
"proxy": false
},
"-222736766326572": {
"typeName": "sample_column_type",
"attributes": {
"qualifiedName": "company_id@cl1",
"dataType": "double",
"name": "company_id",
"comment": "company id"
},
"guid": "-222736766326572",
"isIncomplete": false,
"provenanceType": 0,
"version": 0,
"relationshipAttributes": {
"table": {
"guid": "-222736766326573",
"typeName": "sample_table_type"
}
},
"classifications": [{
"typeName": "sample_finance_Tag",
"entityStatus": "ACTIVE"
}],
"proxy": false
}
},
"entity": {
"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
#!/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 logging
from apache_atlas.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
import getpass
LOG = logging.getLogger('sample-example')
class SampleApp:
def __init__(self):
self.created_entity = None
def main(self):
url = input("Enter Atlas URL: ")
username = input("Enter username: ")
password = getpass.getpass('Enter password: ')
client = AtlasClient(url, username, password)
# Typedef examples
LOG.info("\n")
LOG.info("---------- Creating Sample Types -----------")
typedef = TypeDefExample(client)
typedef.create_type_def()
typedef.print_typedefs()
# Entity example
LOG.info("\n")
LOG.info("---------- Creating Sample Entities -----------")
entity = EntityExample(client)
entity.create_entities()
self.created_entity = entity.get_table_entity()
if self.created_entity and self.created_entity['guid']:
entity.get_entity_by_guid(self.created_entity['guid'])
# Lineage Examples
LOG.info("\n")
LOG.info("---------- Lineage example -----------")
self.__lineage_example(client)
# Discovery Example
LOG.info("\n")
LOG.info("---------- Search example -----------")
self.__discovery_example(client)
# Glossary Examples
LOG.info("\n")
LOG.info("---------- Glossary Example -----------")
self.__glossary_example(client)
LOG.info("\n")
LOG.info("---------- Deleting Entities -----------")
entity.remove_entities()
def __glossary_example(self, client):
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 __lineage_example(self, client):
lineage = LineageExample(client)
if self.created_entity:
lineage.lineage(self.created_entity['guid'])
else:
LOG.info("Create entity first to get lineage info")
def __discovery_example(self, client):
discovery = DiscoveryExample(client)
discovery.dsl_search()
if not self.created_entity:
LOG.info("Create entity first to get search info")
return
discovery.quick_search(self.created_entity['typeName'])
discovery.basic_search(self.created_entity['typeName'], METRIC_CLASSIFICATION, self.created_entity['attributes'][NAME])
if __name__ == "__main__":
SampleApp().main()
\ 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 logging
import utils
from apache_atlas.model.discovery import SearchFilter
from apache_atlas.model.typedef import AtlasTypesDef
import json
LOG = logging.getLogger('sample-example')
class TypeDefExample:
SAMPLE_APP_TYPES = {
utils.PROCESS_TYPE,
utils.COLUMN_TYPE,
utils.TABLE_TYPE,
utils.DATABASE_TYPE,
utils.PII_TAG,
utils.CLASSIFICATION,
utils.FINANCE_TAG,
utils.METRIC_CLASSIFICATION}
def __init__(self, client):
self.typesDef = None
self.client = client
def create_type_def(self):
try:
if not self.typesDef:
with open('request_json/typedef_create.json') as f:
typedef = json.load(f)
self.typesDef = self.__create(typedef)
except Exception as e:
LOG.exception("Error in creating typeDef.")
def print_typedefs(self):
for type_name in TypeDefExample.SAMPLE_APP_TYPES:
filter_params = {"name": type_name}
search = SearchFilter(filter_params)
response = self.client.typedef.get_all_typedefs(search)
if response:
LOG.info("Created type: [%s]", type_name)
def remove_typedefs(self):
if not self.typesDef:
LOG.info("There is no typeDef to delete.")
return
for type_name in TypeDefExample.SAMPLE_APP_TYPES:
self.client.typedef.delete_type_by_name(type_name)
self.typesDef = None
LOG.info("Deleted typeDef successfully!")
def __create(self, type_def):
types_to_create = AtlasTypesDef().__dict__
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:
types_to_create['enumDefs'].append(enum_def)
for struct_def in type_def['structDefs']:
if self.client.typedef.type_with_name_exists(struct_def['name']):
LOG.info("Type with name %s already exists. Skipping.", struct_def['name'])
else:
types_to_create['structDefs'].append(struct_def)
for classification_def in type_def['classificationDefs']:
if self.client.typedef.type_with_name_exists(classification_def['name']):
LOG.info("Type with name %s already exists. Skipping.", classification_def['name'])
else:
types_to_create['classificationDefs'].append(classification_def)
for entity_def in type_def['entityDefs']:
if self.client.typedef.type_with_name_exists(entity_def['name']):
LOG.info("Type with name %s already exists. Skipping.", entity_def['name'])
else:
types_to_create['entityDefs'].append(entity_def)
for relationship_def in type_def['relationshipDefs']:
if self.client.typedef.type_with_name_exists(relationship_def['name']):
LOG.info("Type with name %s already exists. Skipping.", relationship_def['name'])
else:
types_to_create['relationshipDefs'].append(relationship_def)
for business_metadata_def in type_def['businessMetadataDefs']:
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'])
else:
types_to_create['businessMetadataDefs'].append(business_metadata_def)
return self.client.typedef.create_atlas_typedefs(types_to_create)
\ 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.
NAME = "name"
DESCRIPTION = "description"
PII_TAG = "sample_pii_Tag"
FINANCE_TAG = "sample_finance_Tag"
CLASSIFICATION = "classification"
METRIC_CLASSIFICATION = "Metric"
DATABASE_TYPE = "sample_db_type"
PROCESS_TYPE = "sample_process_type"
TABLE_TYPE = "sample_table_type"
COLUMN_TYPE = "sample_column_type"
TABLE_DATABASE_TYPE = "sample_Table_DB"
TABLE_COLUMNS_TYPE = "sample_Table_Columns"
ENUM_TABLE_TYPE = "tableType"
BUSINESS_METADATA_TYPE = "bmWithAllTypes"
BUSINESS_METADATA_TYPE_MV = "bmWithAllTypesMV"
STRUCT_TYPE_SERDE = "serdeType"
\ No newline at end of file
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.
\ No newline at end of file
# Atlas Python Client
This is a python library for Atlas. Users can integrate with Atlas using the python client.
Currently, compatible with Python 3.5+
## Installation
Use the package manager [pip](https://pip.pypa.io/en/stable/) to install python client for Atlas.
```bash
# After publishing apache-atlas use
> pip install apache-atlas
```
Verify if apache-atlas client is installed:
```bash
> pip list
Package Version
------------ ---------
apache-atlas 0.0.1
```
## Usage
```python create_glossary.py```
```python
# create_glossary.py
from apache_atlas.base_client import AtlasClient
from apache_atlas.model.glossary import AtlasGlossary
client = AtlasClient("http://localhost:31000", "admin", "admin123")
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)
```
For more examples, checkout `sample-app` python project in atlas-examples module.
\ 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 logging
from logging.config import dictConfig
logging_config = dict(
version=1,
formatters={
'f': {'format':
'%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
},
handlers={
'h': {'class': 'logging.StreamHandler',
'formatter': 'f',
'level': logging.DEBUG}
},
root={
'handlers': ['h'],
'level': logging.INFO,
},
)
dictConfig(logging_config)
logger = logging.getLogger()
\ 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 copy
import os
from http import HTTPStatus
from requests import Session
import json
import logging
import logging.config
from apache_atlas.utils import CustomEncoder, HttpMethod
from apache_atlas.client.typedef import TypeDefClient
from apache_atlas.client.discovery import DiscoveryClient
from apache_atlas.client.entity import EntityClient
from apache_atlas.client.glossary import GlossaryClient
from apache_atlas.client.lineage import LineageClient
from apache_atlas.client.relationship import RelationshipClient
from apache_atlas.exceptions import AtlasServiceException
LOG = logging.getLogger('apache_atlas')
class AtlasClient:
def __init__(self, host, username, password):
session = Session()
session.auth = (username, password)
self.host = host
self.session = session
self.request_params = {'headers': {}}
self.typedef = TypeDefClient(self)
self.entity = EntityClient(self)
self.lineage = LineageClient(self)
self.discovery = DiscoveryClient(self)
self.glossary = GlossaryClient(self)
self.relationship = RelationshipClient(self)
def call_api(self, api, response_type=None, query_params=None, request_obj=None):
params = copy.deepcopy(self.request_params)
path = os.path.join(self.host, api.path)
params['headers']['Accept'] = api.consumes
params['headers']['Content-type'] = api.produces
print(path)
if query_params:
params['params'] = query_params
if request_obj:
params['data'] = json.dumps(request_obj, indent=4, cls=CustomEncoder)
if LOG.isEnabledFor(logging.DEBUG):
LOG.debug("------------------------------------------------------")
LOG.debug("Call : %s %s", api.method, path)
LOG.debug("Content-type : %s", api.consumes)
LOG.debug("Accept : %s", api.produces)
response = None
if api.method == HttpMethod.GET:
response = self.session.get(path, **params)
elif api.method == HttpMethod.POST:
response = self.session.post(path, **params)
elif api.method == HttpMethod.PUT:
response = self.session.put(path, **params)
elif api.method == HttpMethod.DELETE:
response = self.session.delete(path, **params)
if response is not None:
LOG.debug("HTTP Status: %s", response.status_code)
if response is None:
return None
elif response.status_code == api.expected_status:
if not response_type:
return None
try:
if response.content:
if LOG.isEnabledFor(logging.DEBUG):
LOG.debug("<== __call_api(%s,%s,%s), result = %s", vars(api), params, request_obj, response)
LOG.debug(response.json())
if response_type == str:
return json.dumps(response.json())
return response_type(**response.json())
else:
return None
except Exception as e:
print(e)
LOG.exception("Exception occurred while parsing response with msg: %s", e)
raise AtlasServiceException(api, response)
elif response.status_code == HTTPStatus.SERVICE_UNAVAILABLE:
LOG.error("Atlas Service unavailable. HTTP Status: %s", HTTPStatus.SERVICE_UNAVAILABLE)
return None
else:
raise AtlasServiceException(api, response)
\ 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.
\ 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.
from http import HTTPStatus
from apache_atlas.model.discovery import AtlasSearchResult, AtlasUserSavedSearch, AtlasSuggestionsResult, AtlasQuickSearchResult
from apache_atlas.utils import API, HttpMethod, BASE_URI
class DiscoveryClient:
DISCOVERY_URI = BASE_URI + "v2/search"
DSL_SEARCH_URI = DISCOVERY_URI + "/dsl"
FULL_TEXT_SEARCH_URI = DISCOVERY_URI + "/fulltext"
BASIC_SEARCH_URI = DISCOVERY_URI + "/basic"
FACETED_SEARCH_URI = BASIC_SEARCH_URI
SAVED_SEARCH_URI = DISCOVERY_URI + "/saved"
QUICK_SEARCH_URI = DISCOVERY_URI + "/quick"
DSL_SEARCH = API(DSL_SEARCH_URI, HttpMethod.GET, HTTPStatus.OK)
FULL_TEXT_SEARCH = API(FULL_TEXT_SEARCH_URI, HttpMethod.GET, HTTPStatus.OK)
BASIC_SEARCH = API(BASIC_SEARCH_URI, HttpMethod.GET, HTTPStatus.OK)
FACETED_SEARCH = API(FACETED_SEARCH_URI, HttpMethod.POST, HTTPStatus.OK)
ATTRIBUTE_SEARCH = API(DISCOVERY_URI + "/attribute", HttpMethod.GET, HTTPStatus.OK)
RELATIONSHIP_SEARCH = API(DISCOVERY_URI + "/relationship", HttpMethod.GET, HTTPStatus.OK)
QUICK_SEARCH_WITH_GET = API(QUICK_SEARCH_URI, HttpMethod.GET, HTTPStatus.OK)
QUICK_SEARCH_WITH_POST = API(QUICK_SEARCH_URI, HttpMethod.POST, HTTPStatus.OK)
GET_SUGGESTIONS = API(DISCOVERY_URI + "/suggestions", HttpMethod.GET, HTTPStatus.OK)
# Saved Search
GET_SAVED_SEARCHES = API(SAVED_SEARCH_URI, HttpMethod.GET, HTTPStatus.OK)
GET_SAVED_SEARCH = API(SAVED_SEARCH_URI + "/{search_name}", HttpMethod.GET, HTTPStatus.OK)
ADD_SAVED_SEARCH = API(SAVED_SEARCH_URI, HttpMethod.POST, HTTPStatus.OK)
UPDATE_SAVED_SEARCH = API(SAVED_SEARCH_URI, HttpMethod.PUT, HTTPStatus.OK)
DELETE_SAVED_SEARCH = API(SAVED_SEARCH_URI + "/{guid}", HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
EXECUTE_SAVED_SEARCH_BY_NAME = API(SAVED_SEARCH_URI + "/execute/{search_name}", HttpMethod.GET, HTTPStatus.OK)
EXECUTE_SAVED_SEARCH_BY_GUID = API(SAVED_SEARCH_URI + "/execute/guid/{search_guid}", HttpMethod.GET, HTTPStatus.OK)
QUERY = "query"
LIMIT = "limit"
OFFSET = "offset"
STATUS = "Status"
def __init__(self, client):
self.client = client
def dsl_search(self, query):
query_params = {DiscoveryClient.QUERY, query}
return self.client.call_api(DiscoveryClient.DSL_SEARCH, AtlasSearchResult, query_params)
def dsl_search_with_params(self, query, limit, offset):
query_params = {DiscoveryClient.QUERY: query, DiscoveryClient.LIMIT: limit, DiscoveryClient.OFFSET: offset}
return self.client.call_api(DiscoveryClient.DSL_SEARCH, AtlasSearchResult, query_params)
def full_text_search(self, query):
query_params = {DiscoveryClient.QUERY, query}
return self.client.call_api(DiscoveryClient.FULL_TEXT_SEARCH, AtlasSearchResult, query_params)
def full_text_search_with_params(self, query, limit, offset):
query_params = {DiscoveryClient.QUERY: query, DiscoveryClient.LIMIT: limit, DiscoveryClient.OFFSET: offset}
return self.client.call_api(DiscoveryClient.FULL_TEXT_SEARCH, AtlasSearchResult, query_params)
def basic_search(self, type_name, classification, query, exclude_deleted_entities, limit, offset):
query_params = {"typeName": type_name, "classification": classification, DiscoveryClient.QUERY: query,
"excludeDeletedEntities": exclude_deleted_entities, DiscoveryClient.LIMIT: limit,
DiscoveryClient.OFFSET: offset }
return self.client.call_api(DiscoveryClient.BASIC_SEARCH, AtlasSearchResult, query_params)
def faceted_search(self, search_parameters):
return self.client.call_api(DiscoveryClient.FACETED_SEARCH, AtlasSearchResult, search_parameters)
def attribute_search(self, type_name, attr_name, attr_value_prefix, limit, offset):
query_params = {"attrName": attr_name, "attrValuePrefix": attr_value_prefix, "typeName": type_name,
DiscoveryClient.LIMIT: limit, DiscoveryClient.OFFSET: offset}
return self.client.call_api(DiscoveryClient.ATTRIBUTE_SEARCH, AtlasSearchResult, query_params)
def relationship_search(self, guid, relation, sort_by_attribute, sort_order, exclude_deleted_entities, limit, offset):
query_params = {"guid": guid, "relation": relation, "sortBy": sort_by_attribute,
"excludeDeletedEntities": exclude_deleted_entities,
DiscoveryClient.LIMIT: limit, DiscoveryClient.OFFSET: offset}
if sort_order:
query_params["sortOrder"] = str(sort_order)
return self.client.call_api(DiscoveryClient.RELATIONSHIP_SEARCH, AtlasSearchResult, query_params)
def quick_search(self, query, type_name, exclude_deleted_entities, limit, offset):
query_params = {"query": query, "typeName": type_name, "excludeDeletedEntities": exclude_deleted_entities,
DiscoveryClient.LIMIT: limit, DiscoveryClient.OFFSET: offset}
return self.client.call_api(DiscoveryClient.QUICK_SEARCH_WITH_GET, AtlasQuickSearchResult, query_params)
def quick_search_with_param(self, quick_search_parameters):
return self.client.call_api(DiscoveryClient.QUICK_SEARCH_WITH_POST, AtlasQuickSearchResult, None,
quick_search_parameters)
# fieldName should be the parameter on which indexing is enabled such as "qualifiedName"
def get_suggestions(self, prefix_string, field_name):
query_params = {}
if not prefix_string:
query_params["prefixString"] = prefix_string
if not field_name:
query_params["fieldName"] = field_name
return self.client.call_api(DiscoveryClient.GET_SUGGESTIONS, AtlasSuggestionsResult, query_params)
def get_saved_searches(self, user_name):
query_params = {"user", user_name}
return self.client.call_api(DiscoveryClient.GET_SAVED_SEARCHES, list, query_params)
def get_saved_search(self, user_name, search_name):
query_params = {"user", user_name}
return self.client.call_api(DiscoveryClient.GET_SAVED_SEARCH.format_path({'search_name': search_name}),
AtlasUserSavedSearch, query_params)
def add_saved_search(self, saved_search):
return self.client.call_api(DiscoveryClient.ADD_SAVED_SEARCH, AtlasUserSavedSearch, None, saved_search)
def update_saved_search(self, saved_search):
return self.client.call_api(DiscoveryClient.UPDATE_SAVED_SEARCH, AtlasUserSavedSearch, None, saved_search)
def delete_saved_search(self, guid):
return self.client.call_api(DiscoveryClient.DELETE_SAVED_SEARCH.format_map({'guid': guid}))
def execute_saved_search(self, user_name, search_name):
query_params = {"user", user_name}
return self.client.call_api(DiscoveryClient.EXECUTE_SAVED_SEARCH_BY_NAME.format_map({'search_name': search_name}),
AtlasSearchResult, query_params)
def execute_saved_search(self, search_guid):
return self.client.call_api(DiscoveryClient.EXECUTE_SAVED_SEARCH_BY_GUID.format_map({'search_guid': search_guid}),
AtlasSearchResult)
\ 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.
from http import HTTPStatus
from apache_atlas.model.lineage import AtlasLineageInfo
from apache_atlas.utils import BASE_URI, API, HttpMethod, attributes_to_params
class LineageClient:
LINEAGE_URI = BASE_URI + "v2/lineage"
LINEAGE_INFO = API(LINEAGE_URI, HttpMethod.GET, HTTPStatus.OK)
GET_LINEAGE_BY_ATTRIBUTES = API(LINEAGE_URI + "/uniqueAttribute/type/", HttpMethod.GET, HTTPStatus.OK)
def __init__(self, client):
self.client = client
def get_lineage_info(self, guid, direction, depth):
query_params = {"direction": direction, "depth": depth}
return self.client.call_api(LineageClient.LINEAGE_INFO.format_path_with_params(guid), AtlasLineageInfo, query_params)
def get_lineage_info_attr(self, type_name, attributes, direction, depth):
query_params = attributes_to_params(attributes, {"direction": direction, "depth": depth})
return self.client.call_api(LineageClient.GET_LINEAGE_BY_ATTRIBUTES.format_path_with_params(type_name), AtlasLineageInfo, query_params)
\ 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.
from http import HTTPStatus
from apache_atlas.model.relationship import AtlasRelationshipWithExtInfo, AtlasRelationship
from apache_atlas.utils import BASE_URI, API, HttpMethod
class RelationshipClient:
RELATIONSHIPS_URI = BASE_URI + "v2/relationship/"
BULK_HEADERS = "bulk/headers"
BULK_SET_CLASSIFICATIONS = "bulk/setClassifications"
GET_RELATIONSHIP_BY_GUID = API(RELATIONSHIPS_URI + "guid", HttpMethod.GET, HTTPStatus.OK)
CREATE_RELATIONSHIP = API(RELATIONSHIPS_URI, HttpMethod.POST, HTTPStatus.OK)
UPDATE_RELATIONSHIP = API(RELATIONSHIPS_URI, HttpMethod.PUT, HTTPStatus.OK)
DELETE_RELATIONSHIP_BY_GUID = API(RELATIONSHIPS_URI + "guid", HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
def __init__(self, client):
self.client = client
def get_relationship_by_guid(self, guid):
return self.client.call_api(RelationshipClient.GET_RELATIONSHIP_BY_GUID.format_path_with_params(guid), AtlasRelationshipWithExtInfo)
def get_relationship_by_guid(self, guid, extended_info):
query_params = {"extendedInfo": extended_info}
return self.client.call_api(RelationshipClient.GET_RELATIONSHIP_BY_GUID.format_path_with_params(guid), AtlasRelationshipWithExtInfo, query_params)
def create_relationship(self, relationship):
return self.client.call_api(RelationshipClient.CREATE_RELATIONSHIP, AtlasRelationship, relationship)
def update_relationship(self, relationship):
return self.client.call_api(RelationshipClient.UPDATE_RELATIONSHIP, AtlasRelationship, relationship)
def delete_relationship_by_guid(self, guid):
return self.client.call_api(RelationshipClient.DELETE_RELATIONSHIP_BY_GUID.format_path_with_params(guid))
\ 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.
from http import HTTPStatus
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:
TYPES_API = BASE_URI + "v2/types/"
TYPEDEFS_API = TYPES_API + "typedefs/"
TYPEDEF_BY_NAME = TYPES_API + "typedef/name"
TYPEDEF_BY_GUID = TYPES_API + "typedef/guid"
GET_BY_NAME_TEMPLATE = TYPES_API + "{path_type}/name/{name}"
GET_BY_GUID_TEMPLATE = TYPES_API + "{path_type}/guid/{guid}"
GET_TYPEDEF_BY_NAME = API(TYPEDEF_BY_NAME, HttpMethod.GET, HTTPStatus.OK)
GET_TYPEDEF_BY_GUID = API(TYPEDEF_BY_GUID, HttpMethod.GET, HTTPStatus.OK)
GET_ALL_TYPE_DEFS = API(TYPEDEFS_API, HttpMethod.GET, HTTPStatus.OK)
GET_ALL_TYPE_DEF_HEADERS = API(TYPEDEFS_API + "headers", HttpMethod.GET, HTTPStatus.OK)
CREATE_TYPE_DEFS = API(TYPEDEFS_API, HttpMethod.POST, HTTPStatus.OK)
DELETE_TYPE_DEFS = API(TYPEDEFS_API, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
DELETE_TYPE_DEF_BY_NAME = API(TYPEDEF_BY_NAME, HttpMethod.DELETE, HTTPStatus.NO_CONTENT)
def __init__(self, client):
self.client = client
def get_all_typedefs(self, search_filter):
return self.client.call_api(TypeDefClient.GET_ALL_TYPE_DEFS, AtlasTypesDef, search_filter.params)
def get_all_typedef_headers(self, search_filter):
return self.client.call_api(TypeDefClient.GET_ALL_TYPE_DEF_HEADERS, list, search_filter.params)
def type_with_guid_exists(self, guid):
try:
obj = self.client.call_api(TypeDefClient.GET_TYPEDEF_BY_GUID.format_path_with_params(guid), str)
if not obj:
return False
except Exception as e:
return False
return True
def type_with_name_exists(self, name):
try:
obj = self.client.call_api(TypeDefClient.GET_TYPEDEF_BY_NAME.format_path_with_params(name), str)
if not obj:
return False
except Exception as e:
return False
return True
def get_enumdef_by_name(self, name):
return self.__get_typedef_by_name(name, AtlasEnumDef)
def get_enumdef_by_guid(self, guid):
return self.__get_typedef_by_guid(guid, AtlasEntityDef)
def get_structdef_by_name(self, name):
return self.__get_typedef_by_name(name, AtlasStructDef)
def get_structdef_by_guid(self, guid):
return self.__get_typedef_by_guid(guid, AtlasStructDef)
def get_classificationdef_by_name(self, name):
return self.__get_typedef_by_name(name, AtlasClassificationDef)
def get_Classificationdef_by_guid(self, guid):
return self.__get_typedef_by_guid(guid, AtlasClassificationDef)
def get_entitydef_by_name(self, name):
return self.__get_typedef_by_name(name, AtlasEntityDef)
def get_entitydef_by_guid(self, guid):
return self.__get_typedef_by_guid(guid, AtlasEntityDef)
def get_relationshipdef_by_name(self, name):
return self.__get_typedef_by_name(name, AtlasRelationshipDef)
def get_relationshipdef_by_guid(self, guid):
return self.__get_typedef_by_guid(guid, AtlasRelationshipDef)
def get_businessmetadatadef_by_name(self, name):
return self.__get_typedef_by_name(name, AtlasBusinessMetadataDef)
def get_businessmetadatadef_by_guid(self, guid):
return self.__get_typedef_by_guid(guid, AtlasBusinessMetadataDef)
def create_atlas_typedefs(self, types_def):
return self.client.call_api(TypeDefClient.CREATE_TYPE_DEFS, AtlasTypesDef, None, types_def)
def update_atlas_typedefs(self, types_def):
return self.client.call_api(TypeDefClient.UPDATE_TYPE_DEFS, AtlasTypesDef, None, types_def)
def delete_atlas_typedefs(self, types_def):
return self.client.call_api(TypeDefClient.DELETE_TYPE_DEFS, None, types_def)
def delete_type_by_name(self, type_name):
return self.client.call_api(TypeDefClient.DELETE_TYPE_DEF_BY_NAME.format_path_with_params(type_name))
def __get_typedef_by_name(self, name, typedef_class):
path_type = self.__get_path_for_type(typedef_class);
api = API(TypeDefClient.GET_BY_NAME_TEMPLATE, HttpMethod.GET, HTTPStatus.OK)
return self.client.call_api(api.format_path({'path_type': path_type, 'name': name}), typedef_class)
def __get_typedef_by_guid(self, guid, typedef_class):
path_type = self.__get_path_for_type(typedef_class)
api = API(TypeDefClient.GET_BY_GUID_TEMPLATE, HttpMethod.GET, HTTPStatus.OK)
return self.client.call_api(api.format_path({'path_type': path_type, 'guid': guid}), typedef_class)
def __get_path_for_type(self, typedef_class):
if issubclass(AtlasEnumDef, typedef_class):
return "enumdef"
if issubclass(AtlasEntityDef, typedef_class):
return "entitydef"
if issubclass(AtlasClassificationDef, typedef_class):
return "classificationdef"
if issubclass(AtlasStructDef, typedef_class):
return "structdef"
if issubclass(AtlasRelationshipDef, typedef_class):
return "relationshipdef"
if issubclass(AtlasBusinessMetadataDef, typedef_class):
return "businessmetadatadef"
return ""
\ 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.
class AtlasServiceException(Exception):
"""Exception raised for errors in API calls.
Attributes:
api -- api endpoint which caused the error
response -- response from the server
"""
def __init__(self, api, response):
msg = ""
if api:
msg = "Metadata service API {method} : {path} failed".format_map({'method': api.method, 'path': api.path})
if response.content:
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 " \
"Response Body is :{response}". \
format_map({'url': response.url, 'method': api.method, 'status': status, 'response': response.json()})
self.message = msg
super().__init__(self.message)
\ 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.
\ 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
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 []
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 SortOrder(enum.Enum):
sort_order = enum.Enum('sort_order', 'ASCENDING DESCENDING', module=__name__)
class AttributeSearchResult:
def __init__(self, name=None, values=None):
self.name = name
self.values = values if values is not None else []
class AtlasFullTextResult:
def __init__(self, entity=None, score=None):
self.entity = entity
self.score = score
class AtlasQuickSearchResult:
def __init__(self, searchResults=None, aggregationMetrics=None):
self.searchResults = searchResults
self.aggregationMetrics = aggregationMetrics if aggregationMetrics is not None else {}
class AtlasAggregationEntry:
def __init__(self, name=None, count=None):
self.name = name
self.count = count
class QuickSearchParameters:
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 AtlasSuggestionsResult:
def __init__(self, suggestions=None, prefixString=None, fieldName=None):
self.suggestions = suggestions if suggestions is not None else []
self.prefixString = prefixString
self.fieldName = fieldName
class AtlasUserSavedSearch(AtlasBaseModelObject):
saved_search_type_enum = enum.Enum('saved_search_type_enum', 'BASIC ADVANCED', module=__name__)
def __init__(self, guid=None, ownerName=None, name=None, searchType=None, searchParameters=None, uiParameters=None):
super().__init__(guid)
self.ownerName = ownerName
self.name = 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 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 AtlasBaseModelObject
class AtlasGlossaryBaseObject(AtlasBaseModelObject):
def __init__(self, guid=None, qualifiedName=None, name=None, shortDescription=None,
longDescription=None, additionalAttributes=None, classifications=None):
super().__init__(guid)
self.qualifiedName = qualifiedName
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):
def __init__(self, guid=None, qualifiedName=None, name=None, shortDescription=None, longDescription=None,
additionalAttributes=None, classifications=None, language=None, usage=None, terms=None, categories=None):
super().__init__(guid, qualifiedName, name, shortDescription, longDescription, additionalAttributes, classifications)
self.language = language
self.usage = usage
self.terms = terms if terms is not None else set()
self.categories = categories if categories is not None else set()
class AtlasRelatedTermHeader:
status_enum = enum.Enum('status_enum', 'DRAFT ACTIVE DEPRECATED OBSOLETE OTHER', module=__name__)
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
class AtlasRelatedCategoryHeader:
def __init__(self, categoryGuid=None, parentCategoryGuid=None, relationGuid=None, displayText=None, description=None):
self.categoryGuid = categoryGuid
self.parentCategoryGuid = parentCategoryGuid
self.relationGuid = relationGuid
self.displayText = displayText
self.description = description
class AtlasGlossaryExtInfo(AtlasGlossary):
def __init__(self, guid=None, qualifiedName=None, name=None, shortDescription=None, longDescription=None, additionalAttributes=None,
classifications=None, language=None, usage=None, terms=None, categories=None, termInfo=None, categoryInfo=None):
super().__init__(guid, qualifiedName, name, shortDescription, longDescription,
additionalAttributes, classifications, language, usage, terms, categories)
self.termInfo = termInfo if termInfo is not None else {}
self.categoryInfo = categoryInfo if categoryInfo is not None else {}
class AtlasTermRelationshipStatus(enum.Enum):
DRAFT = 0
ACTIVE = 1
DEPRECATED = 2
OBSOLETE = 3
OTHER = 99
class AtlasGlossaryTerm(AtlasGlossaryBaseObject):
def __init__(self, guid=None, qualifiedName=None, name=None, shortDescription=None, longDescription=None,
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
self.examples = examples if examples is not None else []
self.abbreviation = abbreviation
self.usage = usage
# Attributes derived from relationships
self.anchor = anchor
self.assignedEntities = assignedEntities if assignedEntities is not None else set()
self.categories = categories if categories is not None else set()
# Related Terms
self.seeAlso = seeAlso if seeAlso is not None else set()
# Term Synonyms
self.synonyms = synonyms if synonyms is not None else set()
# Term antonyms
self.antonyms = antonyms if antonyms is not None else set()
# Term preference
self.preferredTerms = preferredTerms if preferredTerms is not None else set()
self.preferredToTerms = preferredToTerms if preferredToTerms is not None else set()
# Term replacements
self.replacementTerms = replacementTerms if replacementTerms is not None else set()
self.replacedBy = replacedBy if replacedBy is not None else set()
# Term translations
self.translationTerms = translationTerms if translationTerms is not None else set()
self.translatedTerms = translatedTerms if translatedTerms is not None else set()
# Term classification
self.isA = isA if isA is not None else set()
self.classifies = classifies if classifies is not None else set()
# Values for terms
self.validValues = validValues if validValues is not None else set()
self.validValuesFor = validValuesFor if validValuesFor is not None else set()
class AtlasGlossaryHeader:
def __init__(self, glossaryGuid=None, relationGuid=None, displayText=None):
self.glossaryGuid = glossaryGuid if glossaryGuid is not None else ""
self.relationGuid = relationGuid
self.displayText = displayText
class AtlasObjectId:
def __init__(self, guid=None, typeName=None, uniqueAttributes=None):
self.guid = guid if guid is not None else ""
self.typeName = typeName
self.uniqueAttributes = uniqueAttributes if uniqueAttributes is not None else {}
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 enum
class AtlasLineageInfo:
lineageDirection_enum = enum.Enum('lineageDirection_enum', 'INPUT OUTPUT BOTH', module=__name__)
def __init__(self, baseEntityGuid=None, lineageDirection=None, lineageDepth=None, guidEntityMap=None, relations=None):
self.baseEntityGuid = baseEntityGuid
self.lineageDirection = lineageDirection
self.lineageDepth = lineageDepth
self.guidEntityMap = guidEntityMap if guidEntityMap is not None else {}
self.relations = relations if relations is not None else set()
class LineageRelation:
def __init__(self, fromEntityId=None, toEntityId=None, relationshipId=None):
self.fromEntityId = fromEntityId
self.toEntityId = toEntityId
self.relationshipId = relationshipId
\ 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.model.entity import AtlasStruct
class AtlasRelationship(AtlasStruct):
propagateTags_enum = enum.Enum('propagateTags_enum', 'NONE ONE_TO_TWO TWO_TO_ONE BOTH', module=__name__)
status_enum = enum.Enum('status_enum', 'ACTIVE DELETED', module=__name__)
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 {}
#!/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 json import JSONEncoder
import time
BASE_URI = "api/atlas/"
APPLICATION_JSON = 'application/json'
APPLICATION_OCTET_STREAM = 'application/octet-stream'
MULTIPART_FORM_DATA = 'multipart/form-data'
PREFIX_ATTR = "attr:"
PREFIX_ATTR_ = "attr_"
s_nextId = milliseconds = int(round(time.time() * 1000)) + 1
def list_attributes_to_params(attributes_list, query_params=None):
if not query_params:
query_params = {}
for i, attr in enumerate(attributes_list):
for key, value in attr.items():
new_key = PREFIX_ATTR_ + i + ":" + key
query_params[new_key] = value
return query_params
def attributes_to_params(attributes, query_params=None):
if not query_params:
query_params = {}
if attributes:
for key, value in attributes:
new_key = PREFIX_ATTR + key
query_params[new_key] = value
return query_params
class HttpMethod(enum.Enum):
GET = "GET"
PUT = "PUT"
POST = "POST"
DELETE = "DELETE"
class API:
def __init__(self, path, method, expected_status, consumes=APPLICATION_JSON, produces=APPLICATION_JSON):
self.path = path
self.method = method
self.expected_status = expected_status
self.consumes = consumes
self.produces = produces
def format_path(self, params):
return API(self.path.format_map(params), self.method, self.expected_status, self.consumes, self.produces)
def format_path_with_params(self, *params):
path = self.path
for par in params:
path += "/" + par
return API(path, self.method, self.expected_status, self.consumes, self.produces)
class CustomEncoder(JSONEncoder):
def default(self, o):
if isinstance(o, set):
return list(o)
return o.__dict__
class AtlasBaseModelObject:
def __init__(self, guid=None):
self.guid = guid if guid is not None else "-" + str(s_nextId)
\ No newline at end of file
requests>=2.24
\ 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.
from setuptools import setup, find_packages
# External dependencies
requirements = ['requests>=2.24']
setup(
name='apache-atlas',
version='0.0.1',
author="Apache Atlas",
author_email='dev@atlas.apache.org',
description="Apache Atlas Python Client",
long_description="Apache Atlas Python client",
long_description_content_type="text/markdown",
url="https://github.com/apache/atlas/tree/master/intg/src/main/python",
license='Apache LICENSE 2.0',
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
],
packages=find_packages(),
install_requires=requirements,
include_package_data=True,
zip_safe=False,
keywords='atlas client, apache atlas',
)
\ 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.
\ 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