Skip to main content

SINLI

Introduction and purpose

This package is a libre-free implementation of the SINLI standard. It builds on top of email to allow applications to communicate all sort of operations of the book sector in Spain.

There are 3 main roles in this sector:

  • bookshops
  • distributors
  • editors

There are some other implementations of this standard, but all of those we know about are closed-source, sell for an expensive yearly license, and work only in Window$ Opressing System. Thus, small bookshops, independent editors and distributors get tied to these disrespectful technologies, and represent a huge economic drag for them.

At Devcontrol we are coding for an initiative supported by a union of these independent entities and led by Descontrol. This initiative is sharing the solution to a shared problem, and is adapting the Odoo ERP (business managing software) to be used for both distributors and bookshops. In order to be a complete replacement of those closed-source apps, we are trying to make Odoo speak SINLI ;)

Organisation and code paradigm

This repository is organized following the guidelines for python packages. The actual code source is inside src/sinli/.

This project is object oriented, and makes use of python @dataclass decorator and Enum class. Namely, the main classes are Document and Line. Each SINLI message is a Document, and each one has many Lines. These two classes must be subclassed for each different document type in a separate file, located inside src/sinli/doctype. Additionaly, Line has 2 subclasses, SubjectLine and IdentificationLine that share a common format for all document types.

SINLI details

Transport

SINLI uses the email as a common transport, but can be also fetched via FTP or other means if the parties agree to do so.

Structure

SINLI documents or messages are text-based, one file each, and line-based. There is no special syntax, instead, each line is to be processed separately, and the different fields in each line are split by their byte position in the line. Therefore, each field has a fixed lenght. In fields where the data has variable lenght, the data is padded with spaces in case of text, and ascii 0 characters in case of numerical fields.

SINLI versions

There are no standard-wide versions in SINLI. Instead, each message type has its own version number. New versions are meant to be backwards compatible to older clients. The standaring committee tries to only add fields at the end of the line, not modifying the lengths or meanings of the existing ones. However, they do not commit to it and call for "get what you can" and for a human check before importing to a system. We support implementing different versions of a document type and parsing them accordingly, but will only implement older versions in a case by case basis. SINLI editors do not like developers implementing old versions because in their opinion, it makes users lazier to update. Because of this and other reasons, older versions specifications are not publicly available.

Example code

Read a document from a SINLI file

from sinli import Document

d = Document.from_filename("/path/to/document.sinli")

Generate a SINLI document

from sinli import libros
from sinli.common import SinliCode as c
from stdnum import isbn

# Create a catalog document
catalog = libros.v10.LibrosDoc()
catalog.set_sender("sinli@publisher.example.org", "LIB12345")
catalog.set_recipient("sinli@bookshop.example.org", "LIB98765")

# Create the header line of the doc
header = libros.v10.LibrosDoc.Header()
header.PROVIDER = "Virus Editorial"
catalog.doc_lines.append(header)

# Create one book for the catalog document
book = libros.v10.LibrosDoc.Book()
book.EAN = "9788417870409"
book.ISBN_INVOICE = isbn.format(book.EAN)
book.AUTHORS = "Kristin Ross"
book.TITLE_FULL= "La forma-comuna"
book.PRICE_PV = 12.0
book.TAX_IVA = 4.0
book.PRICE_PVP = book.PRICE_PV / (1 + book.TAX_IVA / 100) # precio sin IVA
book.PRICE_TYPE = c.PRICE_TYPE.FIXED
book.PRICE_TYPE = c.PRICE_TYPE.FIXED
catalog.doc_lines.append(book)

Encode a SINLI document object to string

# SINLI message string
print(str(catalog))

# Debugging string
print(repr(catalog))

Parse a SINLI email subject line

from sinli.subject import Subject

subject_line = "ESFANDEL1234567ESFANDELIB12345ENVIO 08FANDE"
subject = Subject.from_str(subject_line)

print(f'Received a SINLI message: {subject.DOCTYPE} ({subject.get_doctype_desc()})')
# Received a SINLI message: ENVIO (Albarán de envío de distribuidora)

Build a SINLI email subject

# Use `catalog`the v10.LibrosDoc instance from the previous example
subject = catalog.build_subject()
print(f"Send email with subject '{subject}'")
# Send email with subject 'ESFANDELIB12345ESFANDELIB98765LIBROS10FANDE'

Features

Generic

  • Encode and decode SINLI messages
  • Easy parsing of SINLI email subjects.
  • Provide intuitive ways of setting and extracting information
  • Implemented in enum-based OOP in a predictable manner
  • Provide English wording and original, and improved spanish explanations of fields and message types from the standards, ready to check from the IDE and to use for UIs
  • Manage different document versions. Just some of them, but the mechanism is already in use to manage a diverse implementations ecosystem.
  • Protect the programmer as much as possible from the hussle of the standard assuming 1 Byte character encodings.
  • Testing of messages with real samples.
  • Official standards documents in doc/
  • Real-world message samples in res/

For bookshops

  • Albarán de pedido del cliente
  • Albarán de devolución
  • Mensaje de texto
  • Informe de liquidación de ventas
  • Factura o albarán de abono
  • Informe de stocks a CEGAL
  • Albarán de papelería

For distributors

  • Ficha del libro
  • Cambio de precio
  • Albarán de envío
  • Factura de liquidación
  • Cambio de estado de disponibilidad

Development

To be able to run the tests create your own virtualenv

virtualenv .env

And then run the installation process

make install

Metadata

Release files for sinli 1.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sinli 1.5.1
File Size Uploaded Provenance Actions
sinli-1.5.1.tar.gz 72.3 kB Without provenance Details for sinli-1.5.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for sinli 1.5.1
File Interpreter ABI Platform Actions
sinli-1.5.1-py3-none-any.whl Python 3 none any Details for sinli-1.5.1-py3-none-any.whl

Total release size: 136.7 kB

Release files / sinli-1.5.1.tar.gz

Download URL sinli-1.5.1.tar.gz
Size 72.3 kB
Tags Source
SHA-256 checksum
How to use checksums
eb26506bcb59aaf4f18840c40764a94330eaabc4d39a7d15643f50f62a692a6d
BLAKE2b-256 checksum
How to use checksums
de39a14fdf0f29ae349e242523cc44cdb08c61e108c157d7585b3db09ff242eb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Release files / sinli-1.5.1-py3-none-any.whl

Download URL sinli-1.5.1-py3-none-any.whl
Size 64.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
11d3276f61703a68a95d244350994324ea19b4038a464d1919cf729b80dea8fd
BLAKE2b-256 checksum
How to use checksums
8ee9946752707426ae6b23690db806cc841bb1b36b0175d8f2fffb7576d8821f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.5

Security for sinli 1.5.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page