예제 #1
0
def to_service_uid(uid_brain_obj_str):
    """Resolves the passed in element to a valid uid. Returns None if the value
    cannot be resolved to a valid uid
    """
    if api.is_uid(uid_brain_obj_str) and uid_brain_obj_str != "0":
        return uid_brain_obj_str

    if api.is_object(uid_brain_obj_str):
        obj = api.get_object(uid_brain_obj_str)

        if IAnalysisService.providedBy(obj):
            return api.get_uid(obj)

        elif IRoutineAnalysis.providedBy(obj):
            return obj.getServiceUID()

        else:
            logger.error("Type not supported: {}".format(obj.portal_type))
            return None

    if isinstance(uid_brain_obj_str, six.string_types):
        # Maybe is a keyword?
        query = dict(portal_type="AnalysisService",
                     getKeyword=uid_brain_obj_str)
        brains = api.search(query, SETUP_CATALOG)
        if len(brains) == 1:
            return api.get_uid(brains[0])

        # Or maybe a title
        query = dict(portal_type="AnalysisService", title=uid_brain_obj_str)
        brains = api.search(query, SETUP_CATALOG)
        if len(brains) == 1:
            return api.get_uid(brains[0])

    return None
예제 #2
0
    def _to_service(self, thing):
        """Convert to Analysis Service

        :param thing: UID/Catalog Brain/Object/Something
        :returns: Analysis Service object or None
        """

        # Convert UIDs to objects
        if api.is_uid(thing):
            thing = api.get_object_by_uid(thing, None)

        # Bail out if the thing is not a valid object
        if not api.is_object(thing):
            logger.warn("'{}' is not a valid object!".format(repr(thing)))
            return None

        # Ensure we have an object here and not a brain
        obj = api.get_object(thing)

        if IAnalysisService.providedBy(obj):
            return obj

        if IAnalysis.providedBy(obj):
            return obj.getAnalysisService()

        # An object, but neither an Analysis nor AnalysisService?
        # This should never happen.
        portal_type = api.get_portal_type(obj)
        logger.error("ARAnalysesField doesn't accept objects from {} type. "
                     "The object will be dismissed.".format(portal_type))
        return None
예제 #3
0
    def _to_service(self, thing):
        """Convert to Analysis Service

        :param thing: UID/Catalog Brain/Object/Something
        :returns: Analysis Service object or None
        """

        # Convert UIDs to objects
        if api.is_uid(thing):
            thing = api.get_object_by_uid(thing, None)

        # Bail out if the thing is not a valid object
        if not api.is_object(thing):
            logger.warn("'{}' is not a valid object!".format(repr(thing)))
            return None

        # Ensure we have an object here and not a brain
        obj = api.get_object(thing)

        if IAnalysisService.providedBy(obj):
            return obj

        if IAnalysis.providedBy(obj):
            return obj.getAnalysisService()

        # An object, but neither an Analysis nor AnalysisService?
        # This should never happen.
        msg = "ARAnalysesField doesn't accept objects from {} type. " \
            "The object will be dismissed.".format(api.get_portal_type(obj))
        logger.warn(msg)
        return None
예제 #4
0
def create_analysis(context, source, **kwargs):
    """Create a new Analysis.  The source can be an Analysis Service or
    an existing Analysis, and all possible field values will be set to the
    values found in the source object.
    :param context: The analysis will be created inside this object.
    :param source: The schema of this object will be used to populate analysis.
    :param kwargs: The values of any keys which match schema fieldnames will
    be inserted into the corrosponding fields in the new analysis.
    :returns: Analysis object that was created
    :rtype: Analysis
    """
    an_id = kwargs.get('id', source.getKeyword())
    analysis = _createObjectByType("Analysis", context, an_id)
    copy_analysis_field_values(source, analysis, **kwargs)

    # AnalysisService field is not present on actual AnalysisServices.
    if IAnalysisService.providedBy(source):
        analysis.setAnalysisService(source)
    else:
        analysis.setAnalysisService(source.getAnalysisService())

    # Set the interims from the Service
    service_interims = analysis.getAnalysisService().getInterimFields()
    # Avoid references from the analysis interims to the service interims
    service_interims = copy.deepcopy(service_interims)
    analysis.setInterimFields(service_interims)

    analysis.unmarkCreationFlag()
    zope.event.notify(ObjectInitializedEvent(analysis))
    return analysis
예제 #5
0
    def addReferenceAnalysis(self, service):
        """
        Creates a new Reference Analysis object based on this Sample
        Reference, with the type passed in and associates the newly
        created object to the Analysis Service passed in.

        :param service: Object, brain or UID of the Analysis Service
        :param reference_type: type of ReferenceAnalysis, where 'b' is is
        Blank and 'c' is Control
        :type reference_type: A String
        :returns: the newly created Reference Analysis
        :rtype: string
        """
        if api.is_uid(service) or api.is_brain(service):
            return self.addReferenceAnalysis(api.get_object(service))

        if not IAnalysisService.providedBy(service):
            return None

        interim_fields = service.getInterimFields()
        analysis = _createObjectByType("ReferenceAnalysis", self, id=tmpID())
        # Copy all the values from the schema
        # TODO Add Service as a param in ReferenceAnalysis constructor and do
        #      this logic there instead of here
        discard = [
            'id',
        ]
        keys = service.Schema().keys()
        for key in keys:
            if key in discard:
                continue
            if key not in analysis.Schema().keys():
                continue
            val = service.getField(key).get(service)
            # Campbell's mental note:never ever use '.set()' directly to a
            # field. If you can't use the setter, then use the mutator in order
            # to give the value. We have realized that in some cases using
            # 'set' when the value is a string, it saves the value
            # as unicode instead of plain string.
            # analysis.getField(key).set(analysis, val)
            mutator_name = analysis.getField(key).mutator
            mutator = getattr(analysis, mutator_name)
            mutator(val)
        analysis.setAnalysisService(service)
        ref_type = self.getBlank() and 'b' or 'c'
        analysis.setReferenceType(ref_type)
        analysis.setInterimFields(interim_fields)
        analysis.unmarkCreationFlag()
        renameAfterCreation(analysis)
        return analysis
예제 #6
0
def _resolve_items_to_service_uids(items):
    portal = api.portal.get()
    # We need to send a list of service UIDS to setAnalyses function.
    # But we may have received one, or a list of:
    #   AnalysisService instances
    #   Analysis instances
    #   service titles
    #   service UIDs
    #   service Keywords
    service_uids = []
    # Maybe only a single item was passed
    if type(items) not in (list, tuple):
        items = [
            items,
        ]
    for item in items:
        uid = False
        # service objects
        if IAnalysisService.providedBy(item):
            uid = item.UID()
            service_uids.append(uid)
        # Analysis objects (shortcut for eg copying analyses from other AR)
        if IAnalysis.providedBy(item):
            uid = item.getService().UID()
            service_uids.append(uid)
        # Maybe object UID.
        bsc = getToolByName(portal, 'bika_setup_catalog')
        brains = bsc(UID=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
        # Maybe service Title
        bsc = getToolByName(portal, 'bika_setup_catalog')
        brains = bsc(portal_type='AnalysisService', title=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
        # Maybe service Title
        bsc = getToolByName(portal, 'bika_setup_catalog')
        brains = bsc(portal_type='AnalysisService', getKeyword=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
        if not uid:
            raise RuntimeError(
                str(item) + " should be the UID, title, keyword "
                " or title of an AnalysisService.")
    return service_uids
예제 #7
0
    def get(self, instance, **kwargs):
        an_interims = RecordsField.get(self, instance, **kwargs) or []
        if not IAnalysisService.providedBy(instance):
            return an_interims

        # This instance implements IAnalysisService
        calculation = instance.getCalculation()
        if not calculation:
            return an_interims

        # Ensure the service includes the interims from the calculation
        an_keys = map(lambda interim: interim['keyword'], an_interims)
        # Avoid references from the service interims to the calculation interims
        calc_interims = copy.deepcopy(calculation.getInterimFields())
        calc_interims = filter(lambda inter: inter['keyword'] not in an_keys,
                               calc_interims)
        return an_interims + calc_interims
예제 #8
0
def _resolve_items_to_service_uids(items):
    portal = api.portal.get()
    # We need to send a list of service UIDS to setAnalyses function.
    # But we may have received one, or a list of:
    #   AnalysisService instances
    #   Analysis instances
    #   service titles
    #   service UIDs
    #   service Keywords
    service_uids = []
    # Maybe only a single item was passed
    if type(items) not in (list, tuple):
        items = [items, ]
    for item in items:
        uid = False
        # service objects
        if IAnalysisService.providedBy(item):
            uid = item.UID()
            service_uids.append(uid)
        # Analysis objects (shortcut for eg copying analyses from other AR)
        if IAnalysis.providedBy(item):
            uid = item.getService().UID()
            service_uids.append(uid)
        # Maybe object UID.
        bsc = getToolByName(portal, 'bika_setup_catalog')
        brains = bsc(UID=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
        # Maybe service Title
        bsc = getToolByName(portal, 'bika_setup_catalog')
        brains = bsc(portal_type='AnalysisService', title=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
        # Maybe service Keyword
        bsc = getToolByName(portal, 'bika_setup_catalog')
        brains = bsc(portal_type='AnalysisService', getKeyword=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
        if not uid:
            raise RuntimeError(
                str(item) + " should be the UID, title, keyword "
                            " or title of an AnalysisService.")
    return service_uids
예제 #9
0
    def resolve_to_uid(item):
        if api.is_uid(item):
            return item
        elif IAnalysisService.providedBy(item):
            return item.UID()
        elif IRoutineAnalysis.providedBy(item):
            return item.getServiceUID()

        bsc = api.get_tool("bika_setup_catalog")
        brains = bsc(portal_type='AnalysisService', getKeyword=item)
        if brains:
            return brains[0].UID
        brains = bsc(portal_type='AnalysisService', title=item)
        if brains:
            return brains[0].UID
        raise RuntimeError(
            str(item) + " should be the UID, title, keyword "
            " or title of an AnalysisService.")
예제 #10
0
    def _get_service_uid(self, item):
        if api.is_uid(item):
            return item

        if not api.is_object(item):
            logger.warn("Not an UID: {}".format(item))
            return None

        obj = api.get_object(item)
        if IAnalysisService.providedBy(obj):
            return api.get_uid(obj)

        if IAnalysis.providedBy(obj) and IRequestAnalysis.providedBy(obj):
            return obj.getServiceUID()

        # An object, but neither an Analysis nor AnalysisService?
        # This should never happen.
        msg = "ARAnalysesField doesn't accept objects from {} type. " \
              "The object will be dismissed."
        logger.warn(msg.format(api.get_portal_type(obj)))
        return None
예제 #11
0
파일: analysis.py 프로젝트: xispa/bika.lims
def create_analysis(context, source, **kwargs):
    """Create a new Analysis.  The source can be an Analysis Service or
    an existing Analysis, and all possible field values will be set to the
    values found in the source object.
    :param context: The analysis will be created inside this object.
    :param source: The schema of this object will be used to populate analysis.
    :param kwargs: The values of any keys which match schema fieldnames will
    be inserted into the corrosponding fields in the new analysis.
    :returns: Analysis object that was created
    :rtype: Analysis
    """
    an_id = kwargs.get('id', source.getKeyword())
    analysis = _createObjectByType("Analysis", context, an_id)
    copy_analysis_field_values(source, analysis, **kwargs)

    # AnalysisService field is not present on actual AnalysisServices.
    if IAnalysisService.providedBy(source):
        analysis.setAnalysisService(source)
    else:
        analysis.setAnalysisService(source.getAnalysisService())

    analysis.unmarkCreationFlag()
    zope.event.notify(ObjectInitializedEvent(analysis))
    return analysis
예제 #12
0
def _resolve_items_to_service_uids(items):
    """ Returns a list of service uids without duplicates based on the items
    :param items:
        A list (or one object) of service-related info items. The list can be
        heterogeneous and each item can be:
        - Analysis Service instance
        - Analysis instance
        - Analysis Service title
        - Analysis Service UID
        - Analysis Service Keyword
        If an item that doesn't match any of the criterias above is found, the
        function will raise a RuntimeError
    """
    portal = None
    bsc = None
    service_uids = []

    # Maybe only a single item was passed
    if type(items) not in (list, tuple):
        items = [items, ]
    for item in items:
        # service objects
        if IAnalysisService.providedBy(item):
            uid = item.UID()
            service_uids.append(uid)
            continue

        # Analysis objects (shortcut for eg copying analyses from other AR)
        if IAnalysis.providedBy(item):
            uid = item.getService().UID()
            service_uids.append(uid)
            continue

        # An object UID already there?
        if (item in service_uids):
            continue

        # Maybe object UID.
        portal = portal if portal else api.portal.get()
        bsc = bsc if bsc else getToolByName(portal, 'bika_setup_catalog')
        brains = bsc(UID=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
            continue

        # Maybe service Title
        brains = bsc(portal_type='AnalysisService', title=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
            continue

        # Maybe service Keyword
        brains = bsc(portal_type='AnalysisService', getKeyword=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
            continue

        raise RuntimeError(
            str(item) + " should be the UID, title, keyword "
                        " or title of an AnalysisService.")
    return list(set(service_uids))
예제 #13
0
def _resolve_items_to_service_uids(items):
    """ Returns a list of service uids without duplicates based on the items
    :param items:
        A list (or one object) of service-related info items. The list can be
        heterogeneous and each item can be:
        - Analysis Service instance
        - Analysis instance
        - Analysis Service title
        - Analysis Service UID
        - Analysis Service Keyword
        If an item that doesn't match any of the criterias above is found, the
        function will raise a RuntimeError
    """
    portal = None
    bsc = None
    service_uids = []

    # Maybe only a single item was passed
    if type(items) not in (list, tuple):
        items = [
            items,
        ]
    for item in items:
        # service objects
        if IAnalysisService.providedBy(item):
            uid = item.UID()
            service_uids.append(uid)
            continue

        # Analysis objects (shortcut for eg copying analyses from other AR)
        if IAnalysis.providedBy(item):
            uid = item.getService().UID()
            service_uids.append(uid)
            continue

        # An object UID already there?
        if (item in service_uids):
            continue

        # Maybe object UID.
        portal = portal if portal else api.portal.get()
        bsc = bsc if bsc else getToolByName(portal, 'bika_setup_catalog')
        brains = bsc(UID=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
            continue

        # Maybe service Title
        brains = bsc(portal_type='AnalysisService', title=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
            continue

        # Maybe service Keyword
        brains = bsc(portal_type='AnalysisService', getKeyword=item)
        if brains:
            uid = brains[0].UID
            service_uids.append(uid)
            continue

        raise RuntimeError(
            str(item) + " should be the UID, title, keyword "
            " or title of an AnalysisService.")
    return list(set(service_uids))
예제 #14
0
def doActionToAnalysis(source_analysis, action):
    """
    This functions executes the action against the analysis.
    :base: a full analysis object. The new analyses will be cloned from it.
    :action: a dictionary representing an action row.
        [{'action': 'duplicate', ...}, {,}, ...]
    :returns: the new analysis
    """
    if not IRequestAnalysis.providedBy(source_analysis):
        # Only routine analyses (assigned to a Request) are supported
        logger.warn("Only IRequestAnalysis are supported in reflex testing")
        return None

    state = api.get_review_status(source_analysis)
    action_id = action.get('action', '')

    if action_id == "new_analysis":
        # Create a new analysis (different from the original)
        service_uid = action.get("new_analysis", "")
        if not api.is_uid(service_uid):
            logger.error("Not a valid UID: {}".format(service_uid))
            return None
        service = api.get_object_by_uid(service_uid, None)
        if not service or not IAnalysisService.providedBy(service):
            logger.error("No valid service for UID {}".format(service_uid))
            return None

        analysis = create_analysis(source_analysis.aq_parent, service)
        analysis.setSamplePartition(source_analysis.getSamplePartition())
        changeWorkflowState(analysis, "bika_analysis_workflow",
                            "sample_received")
    elif action_id == 'setvisibility':
        target_id = action.get('setvisibilityof', '')
        if target_id == "original":
            analysis = source_analysis
        else:
            analysis = _fetch_analysis_for_local_id(source_analysis, target_id)

    elif action_id == 'repeat' and state != 'retracted':
        # Repeat an analysis consist on cancel it and then create a new
        # analysis with the same analysis service used for the canceled
        # one (always working with the same sample). It'll do a retract
        # action
        doActionFor(source_analysis, 'retract')
        analysis_request = source_analysis.getRequest()
        analysis = analysis_request.getAnalyses(sort_on="created")[-1]
        analysis = api.get_object(analysis)
        analysis.setResult('')

    elif action_id == 'duplicate' or state == 'retracted':
        analysis = duplicateAnalysis(source_analysis)
        analysis.setResult('')

    elif action_id == 'setresult':
        target = action.get('setresulton', '')
        result_value = action.get('setresultdiscrete', '') or \
                       action['setresultvalue']

        if target == 'original':
            analysis = source_analysis.getOriginalReflexedAnalysis()
            analysis.setResult(result_value)

        elif target == 'new':
            # Create a new analysis
            analysis = duplicateAnalysis(source_analysis)
            analysis.setResult(result_value)
            doActionFor(analysis, 'submit')

        else:
            logger.error("Unknown 'setresulton' directive: {}".format(target))
            return None

    else:
        logger.error("Unknown Reflex Rule action: {}".format(action_id))
        return None

    analysis.setReflexRuleAction(action_id)
    analysis.setIsReflexAnalysis(True)
    analysis.setReflexAnalysisOf(source_analysis)
    analysis.setReflexRuleActionsTriggered(
        source_analysis.getReflexRuleActionsTriggered())
    if action.get('showinreport', '') == "invisible":
        analysis.setHidden(True)
    elif action.get('showinreport', '') == "visible":
        analysis.setHidden(False)
    # Setting the original reflected analysis
    if source_analysis.getOriginalReflexedAnalysis():
        analysis.setOriginalReflexedAnalysis(
            source_analysis.getOriginalReflexedAnalysis())
    else:
        analysis.setOriginalReflexedAnalysis(source_analysis)
    analysis.setReflexRuleLocalID(action.get('an_result_id', ''))

    # Setting the remarks to base analysis
    #remarks = get_remarks(action, analysis)
    #analysis.setRemarks(remarks)

    return analysis