Skip to main content

Python library for generating Proligent™ XML files.

Project description

Proligent™ XML Generator for Python™

Build Python Package Index Python Versions

Python™ library for generating Proligent™ XML files. It provides a simple, structured API for building valid import files, reducing manual XML writing and ensuring consistent data formatting. These files are used to import data into Proligent™ Cloud and Proligent™ Analytics.

Tip: Refer to the Proligent™ Manufacturing Information Model to learn how to structure and map your data in Proligent™.

Proligent™ software are designed for Operations Managers, Quality Engineers, Manufacturing Engineers and Test Engineers. This easy-to-use software solution monitors test stations and provides valuable insight into your product line.

Installation instructions

First, install a compatible python version from Python.org.

Then, to install the package in your (virtual) environment, run the following command:

pip install proligent-xml-generator

Getting started

Each layer of the Proligent™ Manufacturing Information Model is represented in the package by an equivalent class. Typing hints are used to indicate what data types are accepted by the objects.

Example 1

from proligent.model import (
    DataWareHouse,
    ExecutionStatusKind,
    Limit,
    LimitExpression,
    Measure,
    OperationRun,
    ProcessRun,
    ProductUnit,
    SequenceRun,
    StepRun,
)
import datetime

if __name__ == "__main__":
    limit = Limit(
        LimitExpression.LOWERBOUND_LEQ_X_LE_HIGHER_BOUND,
        lower_bound=10,
        higher_bound=25,
    )
    measure = Measure(
        value=15,
        status=ExecutionStatusKind.PASS,
        limit=limit,
        time=datetime.datetime.now(),
    )
    step = StepRun(
        name="Step1",
        status=ExecutionStatusKind.PASS,
        measure=measure
    )

    # Create sequence run: remember to keep track of start and end time

    sequence = SequenceRun(
        name="Sequence1",
        status=ExecutionStatusKind.PASS,
        steps=[step],
    )

    # Create operation run: remember to keep track of start and end time

    operation = OperationRun(
        name="Operation1",
        station="Station/readme_example",
        status=ExecutionStatusKind.PASS,
        sequences=[sequence],
    )

    # Create process run: remember to keep track of start and end time

    process = ProcessRun(
        product_unit_identifier="DutSerialNumber",
        product_full_name="Product/readme_example",
        operations=[operation],
        name="Process/readme_example",
        process_mode="PROD",
        status=ExecutionStatusKind.PASS,
    )

    product = ProductUnit(
        product_unit_identifier="DutSerialNumber",
        product_full_name="Product/readme_example",
        manufacturer="Averna",
    )

    warehouse = DataWareHouse(top_process=process, product_unit=product)
    warehouse.save_xml()

Note: For simplicity this example omits the start and end times, so they default to datetime.now. It is highly recommended to set these values with real timestamps when used in the real world.

You can also provide the output path for the XML:

from proligent.model import DataWareHouse
warehouse = DataWareHouse()
warehouse.save_xml(destination=r'C:\path_to\Proligent_file_name.xml')

Example 2

This example shows a second way of ordering calls and constructors, from top to bottom.

from proligent.model import (
    DataWareHouse,
    ExecutionStatusKind,
    Limit,
    LimitExpression,
    Measure,
    OperationRun,
    ProcessRun,
    ProductUnit,
    SequenceRun,
    StepRun,
)
import datetime

if __name__ == "__main__":
    warehouse = DataWareHouse()

    product = warehouse.set_product_unit(
        ProductUnit(
            product_unit_identifier="UutSerialNumber",
            product_full_name="Product/readme_example",
            manufacturer="Averna",
        )
    )

    process = warehouse.set_process_run(
        ProcessRun(
            name="Process/readme_example",
            process_mode="PROD",
            product_unit_identifier="DutSerialNumber",
            product_full_name="Product/readme_example",
        )
    )

    operation = process.add_operation_run(
        OperationRun(
            name="Operation1",
            station="Station/readme_example",
        )
    )

    sequence = operation.add_sequence_run(
        SequenceRun(
            name="Sequence1",
        )
    )

    sequence.add_step_run(
        StepRun(
            name="Step1",
            status=ExecutionStatusKind.PASS,
            measure=Measure(
                value=15,
                time=datetime.datetime.now(),
                status=ExecutionStatusKind.PASS,
                limit=Limit(
                    LimitExpression.LOWERBOUND_LEQ_X_LE_HIGHER_BOUND,
                    lower_bound=10,
                    higher_bound=25,
                ),
            ),
        )
    )

    sequence.complete(status=ExecutionStatusKind.PASS)
    operation.complete(status=ExecutionStatusKind.PASS)
    process.complete(status=ExecutionStatusKind.PASS)
    warehouse.save_xml()

About Names

Most of the "names" (product, station, etc.) in the model can be simple strings, or can be built in hierarchies.

The goal is to allow grouping of items in meaningful categories, which can be useful when selecting items for display or reporting.

Note that the last item in the full name (the "leaf" of the tree) must be meaningful: some reports display only the leaf, for simplicity and brevity. In most cases the full names is also available, but may be less visible (tooltips).

Example: Stations

Country/ManufacturerName/ProductionLine/StationName

Other items in the full station names could be: city, station type, etc.

For stations that can test multiple units in parallel: see test_position_name.

Example: Products

ProductFamily/ProductName/PartNumber

We don't recommend having a version or revision as the leaf of the full product name. This is best recorded as a characteristic, either on the product unit or the operation.

Sequence "Tree"

All sequences are added to the operation. However, typically sequences are organized in "trees".

MainSequence1
    SubSequence1
        SubSubSeq1
        SubSubSeq2
    SubSequence2
MainSequence2
    etc.

To keep the sequences organized in trees like the example above, the sequences names need to include all nodes of the tree, separated by "/".

    sequence = operation.add_sequence_run(SequenceRun(name="MainSequence1/SubSequence1/SubSubSeq1"))
    sequence = operation.add_sequence_run(SequenceRun(name="MainSequence1/SubSequence1/SubSubSeq2"))
    sequence = operation.add_sequence_run(SequenceRun(name="MainSequence1/SubSequence2"))
    sequence = operation.add_sequence_run(SequenceRun(name="MainSequence2"))
    # etc.

It is not necessary to create all nodes (e.g. MainSequence1 and MainSequence1/SubSequence1). However, they can also be created if they need to old steps, characteristics or documents.

Also note that the full sequence name is limited to 2000 characters, and each part to 64 characters.

Process Run ID

By default, the ProcessRunID is automatically generated as a deterministic ID based on the product_full_name, product_unit_identifier, process_mode, and a configurable fixed process start time (default: "2000-01-01").

This ensures that multiple operation runs within the same process refer to the same process run, which is critical for accurate reporting in Proligent.

If you need a fixed ID regardless of field values, you can optionally set the id parameter directly when constructing the ProcessRun.

File Names

The XML files must have the prefix "Proligent_".

The documents attached must have the prefix "Document_".

In case of compressed documents, "CompressedDocument_".

XML Validation

Generated XML can be validated for safety.

from proligent.xml_validate import validate_xml

# This raises an exception if the XML is invalid

validate_xml(r"C:\path_to\Proligent_file_name.xml")

# This safe call returns the status and meta-data about a failure, if any

is_valid, metadata = validate_xml_safe(r"C:\path_to\Proligent_file_name.xml")

if not is_valid:
    print(metadata.path)
    print(metadata.reason)

Configuration

A few parameters are configurable in the package through the use of the UTIL object.

UTIL and Util now live in proligent.util. Backward compatibility is kept, so importing these symbols from proligent.model still works.

  • destination_dir: Specify a different destination directory for the XML files, aside from the default C:\Proligent\IntegrationService\Acquisition.
  • timezone: Specify a different timezone for the provided datetimes (default is the TZ of the local machine). pytz is used for timezone handling. It provides pytz.all_timezones and pytz.common_timezones to list all possible timezones. Alternatively, you can look at this list on Wikipedia.
from proligent.util import UTIL

if __name__ == '__main__':
    UTIL.destination_dir = r'\\NETWORK_SHARE\Acquisition'
    UTIL.timezone = 'America/New_York'

Trademarks

Proligent is a registered trademark, and Averna is a trademark, of Averna Technologies Inc.

Python is a trademark of the Python Software Foundation.

Other product and company names mentioned herein are trademarks or trade names of their respective companies.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

proligent_xml_generator-1.1.2.tar.gz (66.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

proligent_xml_generator-1.1.2-py3-none-any.whl (84.5 kB view details)

Uploaded Python 3

File details

Details for the file proligent_xml_generator-1.1.2.tar.gz.

File metadata

  • Download URL: proligent_xml_generator-1.1.2.tar.gz
  • Upload date:
  • Size: 66.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for proligent_xml_generator-1.1.2.tar.gz
Algorithm Hash digest
SHA256 6ba5661255400d914d474d9f7f0f4bd002bbd10c31f886f1b6d3d7e0ded4b052
MD5 6ee3107c5a3d4be3493c49d6ada0fd08
BLAKE2b-256 656dc380bbd790957f0f25b1b44ee4bb2165079ef71ca2f1f1ca0f72481d0333

See more details on using hashes here.

File details

Details for the file proligent_xml_generator-1.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for proligent_xml_generator-1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0c90c08b3aff073d305879aab0f4bd93643161620e394014b8565c9f1bfa8699
MD5 b44f88dfc0db07ef15b62cfcba3b468f
BLAKE2b-256 b88e00b3b520e249ff418b3cc855f447640e7e9ae9b5873ce6e37bb69cf2bfd7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page