Source code for ocdsextensionregistry.codelist

"""
.. code:: python

    from ocdsextensionregistry import Codelist

Create a new codelist:

.. code:: python

    codelist = Codelist('+partyRole.csv')

Add codes to the codelist (you can provide any iterable, including a :code:`csv.DictReader`):

.. code:: python

    codelist.extend([
        {'Code': 'publicAuthority', 'Title': 'Public authority', 'Description': ''},
        {'Code': 'bidder', 'Title': 'Bidder', 'Description': ''}
    ])

Iterate over the codes in the codelist:

.. code:: python

    [code['Title'] for code in codelist]  # ['Public authority', 'Bidder']

Read the codelists' codes and fieldnames:

.. code:: python

    codelist.codes  # ['publicAuthority', 'bidder']
    codelist.fieldnames  # ['Code', 'Title', 'Description']

Determine whether the codelist adds or removes codes from another codelist:

.. code:: python

    codelist.patch  # True
    codelist.addend  # True
    codelist.subtrahend  # False

Get the name of the codelist it modifies:

.. code:: python

    codelist.basename  # 'partyRole.csv'
"""
import csv
from io import StringIO

from .codelist_code import CodelistCode


[docs] class Codelist:
[docs] def __init__(self, name): self.name = name self.rows = []
def __getitem__(self, index): return self.rows[index] def __iter__(self): yield from self.rows def __len__(self): return len(self.rows)
[docs] def __lt__(self, other): return self.name < other.name
[docs] def __repr__(self): return f'Codelist(name={self.name!r}, rows={self.rows!r})'
[docs] def extend(self, rows, extension_name=None): """ Adds rows to the codelist. """ for row in rows: self.rows.append(CodelistCode(row, extension_name))
[docs] def add_extension_column(self, field_name): """ Adds a column for the name of the extension from which codes originate. """ for row in self.rows: row[field_name] = row.extension_name
[docs] def remove_deprecated_codes(self): """ Removes deprecated codes and the Deprecated column. """ self.rows = [row for row in self.rows if not row.pop('Deprecated', None)]
[docs] def to_csv(self): """ Returns the codelist as CSV content. """ io = StringIO() writer = csv.DictWriter(io, fieldnames=self.fieldnames, lineterminator='\n', extrasaction='ignore') writer.writeheader() writer.writerows(self) return io.getvalue()
@property def codes(self): """ Returns the codes in the codelist. """ return [row['Code'] for row in self.rows] @property def fieldnames(self): """ Returns all fieldnames used in any rows. """ fieldnames = {} # sets are unordered for row in self.rows: for field in row: fieldnames[field] = True return list(fieldnames.keys()) @property def basename(self): """ If the codelist modifies another codelist, returns the latter's name. Otherwise, returns its own name. """ if self.patch: return self.name[1:] return self.name @property def patch(self): """ Returns whether the codelist modifies another codelist. """ return self.name.startswith(('+', '-')) @property def addend(self): """ Returns whether the codelist adds codes to another codelist. """ return self.name.startswith('+') @property def subtrahend(self): """ Returns whether the codelist removes codes from another codelist. """ return self.name.startswith('-')