Package: baton
# baton Python WrapperIntroductionPython 3 Wrapper forbaton,
superseding a [previous implementation in metadata-check]
(https://github.com/wtsi-hgi/metadata-check/blob/9cd5c41b0f2e254fc1d6249a14752bd428587bb7/irods_baton/baton_wrapper.py).The wrapper provides access to most of baton’s functionality.How to usePrerequisitesPython >= 3.5.2baton >= 0.16.4iRODS >= 4.1.9Note: Although older version of baton/iRODS will probably work, the
library is only aimed at the versions specified above.InstallationStable releases can be installed viaPyPI:$pip3installbatonBleeding edge versions can be installed directly from GitHub:$pip3installgit+https://github.com/wtsi-hgi/python-baton-wrapper.git@<commit_id_or_branch_or_tag>#egg=batonTo declare this library as a dependency of your project, add it to yourrequirement.txtfile.APISetupTo use the iRODS API, you must first define a “connection” to an iRODS
server:frombaton.apiimportconnect_to_irods_with_baton,Connection# Setup connection to iRODS using batonirods=connect_to_irods_with_baton("/where/baton/binaries/are/installed/",skip_baton_binaries_validation=False)# type: ConnectionData Objects and CollectionsThe API provides the ability to retrieve models of the data objects and
collections stored on an iRODS server. Similarly to the JSON that baton
provides, the models do not contain the payloads. They do however
provide access to all of the information that baton can retrieve about
an entity, including Access Control Lists (ACLs), custom metadata
(AVUs), the content of collections and information about data object
replicas. All methods provide the option to not load AVUs.frombaton.modelsimportDataObject,Collection,SearchCriterion,ComparisonOperator# Get models of data objects or collections at the given path(s) in iRODSirods.data_object.get_by_path("/collection/data_object",load_metadata=False)# type: DataObject:irods.collection.get_by_path(["/collection","/other_collection"])# type: Sequence[Collection]:# Setup search for data objects or collections based on their metadatasearch_criterion_1=SearchCriterion("attribute","match_value",ComparisonOperator.EQUALS)search_criterion_2=SearchCriterion("other_attribute","other_match_value",ComparisonOperator.LESS_THAN)# Do search to get models of data objects or collectionsirods.data_object.get_by_metadata(search_criterion_1,zone="OptionalZoneRestriction")# type: Sequence[DataObject]irods.collection.get_by_metadata([search_criterion_1,search_criterion_2],load_metadata=False)# type: Sequence[Collection]# Get models of data objects or collections contained within a collection(s)irods.collection.get_all_in_collection("/collection",load_metadata=False)# type: Sequence[Collection]irods.data_object.get_all_in_collection(["/collection","/other_collection"])# type: Sequence[DataObject]Metadata (AVUs)The API provides the ability to both retrieve and manipulate the custom
metadata (AVUs) associated with data objects and collections.Warning: there is currently no support for reading/writing the unit
property of AVUs.Although the type of metadata is the same for both data objects and
collections, due to the way iRODS works, it is necessary to know the
type of entity that a path corresponds to in order to retrieve metadata.frombaton.collectionsimportIrodsMetadatametadata_1=IrodsMetadata({"key":{"value_1"}})metadata_2=IrodsMetadata({"another_key":{"value_1","value_2"}})# Metadata (methods available for both `data_object` and `collection`)irods.data_object.metadata.get_all("/collection/data_object")# type: IrodsMetadatairods.collection.metadata.get_all(["/collection","/other_collection"])# type: Sequence[IrodsMetadata]# `metadata_1` is added to the data object with the first path in the list and `metadata_2` is added to the secondirods.data_object.metadata.add(["/collection/data_object","/other_data_object"],[metadata_1,metadata_2])irods.collection.metadata.add("/collection",metadata_1)irods.data_object.metadata.set("/collection/data_object",metadata_1)# `metadata_1` is added to both collections in the listirods.collection.metadata.set(["/collection","/other_collection"],metadata_1)irods.data_object.metadata.remove(["/collection/data_object","/other_data_object"],[metadata_1,metadata_2])irods.collection.metadata.remove("/collection",metadata_1)irods.data_object.metadata.remove_all("/collection/data_object")irods.collection.metadata.remove_all(["/collection","/other_collection"])Access Control Lists (ACLs)The API provides the ability to both retrieve and manipulate the access
control lists (ACLs) associated with data objects and collections.frombaton.modelsimportAccessControl# ACLs. Note: it is implied that the owner is in the same zone as the entity to which the access control is appliedacl_examples=[AccessControl(User("user_1","zone_user_is_in"),AccessControl.Level.READ),AccessControl(User("group_1","zone_group_is_in"),AccessControl.Level.WRITE),AccessControl("user_1#zone_user_is_in",AccessControl.Level.OWN)]irods.data_object.access_control.get_all("/collection/data_object")# type: Set[AccessControl]irods.collection.access_control.get_all(["/collection","/another/collection"])# type: List[Set[AccessControl]]irods.data_object.access_control.add_or_replace(["/collection/data_object","/another/data_object"],acl_examples[0])irods.collection.access_control.add_or_replace("/collection",acl_examples,recursive=True)irods.data_object.access_control.set("/collection/data_object",acl_examples[1])irods.collection.access_control.set(["/collection","/another/collection"],acl_examples[0],recursive=False)irods.data_object.access_control.revoke(["/collection/data_object","/another/data_object"],acl_examples)irods.collection.access_control.revoke("/collection",acl_examples[1],recursive=True)irods.data_object.access_control.revoke_all(["/collection/data_object","/another/data_object"])irods.collection.access_control.revoke_all("/collection",recursive=True)Custom objects via specific queriesiRODS supports specific queries which return new types of object. In
order to use such custom objects in iRODS via this library, a custom
model of the object should to be made. Then, a subclass ofBatonCustomObjectMapperneeds to be defined to specify how a
specific query (or number of specific queries) can be used to retrieve
from and/or modify the object in iRODS.The API provides the ability to retrieve the queries that are installed
on an iRODS server (ironically, by use of a specific query!):frombaton.modelsimportSpecificQuery# Get specific queries that have been installed on the iRODS serverirods.specific_query.get_all(zone="OptionalZoneRestriction")# type: Sequence[SpecificQuery]JSON Serialization/DeserializationThere are JSON encoders and decoders for nearly all iRODS object models
in this library. These can be used to convert models to/from their baton
defined JSON representations. All serializers/deserializers extendJSONEncoderandJSONDecoder(most through use of thehgijsonlibrary) meaning
that they can be used withPython’s built in ``json`package <https://docs.python.org/3/library/json.html>`__:importjsonfrombaton.jsonimportDataObjectJSONEncoder,DataObjectJSONDecoder,CollectionJSONEncoder,CollectionJSONDecoder,IrodsMetadataJSONEncoder,IrodsMetadataJSONDecoder,AccessControlJSONEncoder,AccessControlJSONDecoderdata_object_as_json_string=json.dumps(data_object,cls=DataObjectJSONEncoder)# type: strdata_object=json.loads(data_object_as_json_string,cls=DataObjectJSONDecoder)# type: DataObjectcollection_as_json_string=json.dumps(collection,cls=CollectionJSONEncoder)# type: strcollection=json.loads(collection_as_json_string,cls=CollectionJSONDecoder)# type: Collectionmetadata_as_json_string=json.dumps(metadata,cls=IrodsMetadataJSONEncoder)# type: strmetadata=json.loads(metadata_as_json_string,cls=IrodsMetadataJSONDecoder)# type: IrodsMetadataacl_as_json_string=json.dumps(metadata,cls=AccessControlJSONEncoder)# type: stracl=json.loads(acl_as_json_string,cls=AccessControlJSONDecoder)# type: List[AccessControl]DevelopmentSetupInstall both library dependencies and the dependencies needed for
testing:$pip3install-q-rrequirements.txt$pip3install-q-rtest_requirements.txtA baton installation is not required.Some tests useDockertherefore a Docker
daemon must be running on the test machine, with the environment
variablesDOCKER_TLS_VERIFY,DOCKER_HOSTandDOCKER_CERT_PATHset.TestingUsing nosetests, in the project directory, run:$nosetests-v--cover-inclusive--testsbaton/tests,baton/tests/_batonTo generate a test coverage report with nosetests:$nosetests-v--with-coverage--cover-package=baton--cover-inclusive--testsbaton/tests,baton/tests/_batonLicenseLGPL license.Copyright (c) 2015, 2016 Genome Research Limited