Skip to main content

A parsing library for the UK's MPAN energy standard

Project description

Limejump logo

mpan

PyPI PyPI License Black 100% Coverage

A library to help you parse the UK energy industry's MPAN number format.

How it works

from mpan import MPAN


mpan = MPAN("A valid MPAN")

Just import the library and pass it the MPAN you want to parse. In response you get a handy MPAN object with a number of convenient properties:

The Basics

The most common use is likely to be in examining the "core":

mpan = MPAN("001112221312345678907")

mpan.top_line    # "00111222"
mpan.core        # "1312345678907"
mpan.identifier  # "12345678"
mpan.is_short    # False
mpan.is_long     # True
mpan.as_short    # "1312345678907"

mpan = MPAN("1312345678907")

mpan.top_line    # None
mpan.core        # "1312345678907"
mpan.identifier  # "12345678"
mpan.is_short    # True
mpan.is_long     # False
mpan.as_short    # "1312345678907"

The Top Line

You can also go deeper though, and interrogate the top line:

mpan = MPAN("001112221312345678907")

mpan.profile_class                       # A ProfileClass instance
mpan.profile_class.identifier            # "00"
mpan.profile_class.description           # "Half-hourly supply (import and export)"
mpan.profile_class.is_valid              # True

mpan.meter_time_switch_code              # A MeterTimeSwitchCode instance
mpan.meter_time_switch_code.identifier   # "111"
mpan.meter_time_switch_code.description  # "DNO specific"
mpan.meter_time_switch_code.is_valid     # True

mpan.line_loss_factor_class              # "222"

Note however that if you don't supply a long MPAN, this library can't help you:

mpan = MPAN("1312345678907")

mpan.profile_class           # None
mpan.meter_time_switch_code  # None
mpan.line_loss_factor_class  # None

The Distributor

The core can also be broken up to look into the distributor, which is a little tricky, since the distributor id can either refer to a DNO (which has a known set of properties) or an IDNO (which has a different set). We handle this discrepancy by returning None in cases where the requested information is unavailable:

mpan = MPAN("2099999999993")

mpan.distributor                   # A Distributor instance
mpan.distributor.identifier        # "20"
mpan.distributor.area              # "Southern England"
mpan.distributor.gsp_group_id      # "_H"
mpan.distributor.operator          # "Scottish & Southern Electricity Networks"
mpan.distributor.participant_id    # "SOUT"
mpan.distributor.is_dno            # True
mpan.distributor.is_idno           # False
mpan.distributor.is_valid          # True
mpan.distributor.licensee          # None
mpan.distributor.mpas_operator_id  # None
mpan.distributor.name              # None

mpan = MPAN("2499999999991")

mpan.distributor                   # A Distributor instance
mpan.distributor.identifier        # "24"
mpan.distributor.area              # None
mpan.distributor.gsp_group_id      # None
mpan.distributor.operator          # None
mpan.distributor.participant_id    # None
mpan.distributor.is_dno            # False
mpan.distributor.is_idno           # True
mpan.distributor.is_valid          # True
mpan.distributor.licensee          # "Independent Power Networks"
mpan.distributor.mpas_operator_id  # "IPNL"
mpan.distributor.name              # "Envoy"

Aliases

For people who want to limit the number of characters they're typing, we recognise a few standard acronyms:

mpan.pc    # Profile Class
mpan.mtc   # Meter Time Switch Code
mpan.llfc  # Line Loss Factor Class

Validation Options

You've got choices for validation. .is_valid() will check your MPAN string and return a boolean value indicating whether it's valid or not, while you can call .check() on an MPAN instance, which will explode with an InvalidMpanError if your string doesn't check out.

An important note about validation

There are four aspects of validation performed by the validation checks below: the profile class and meter time switch code (if provided as part of the top line in a long MPAN) will be checked against a list of known values, the distributor from the core will be similarly checked, and finally the formula for the check digit will be applied.

from mpan import InvalidMPANError, MPAN


MPAN("2499999999991").is_valid          # True
MPAN("2499999999990").is_valid          # False  (bad checksum)
MPAN("8699999999991").is_valid          # False  (bad distributor)
MPAN("001112221312345678907").is_valid  # True
MPAN("991112221312345678907").is_valid  # False  (bad profile class)
MPAN("000002221312345678907").is_valid  # False  (bad meter time switch code)

MPAN("I am not an MPAN")                # InvalidMPANError

try:
    MPAN("2499999999991").check()  # Returns None
    MPAN("2499999999990").check()  # Raises an InvalidMPANError
except InvalidMPANError:
    print("This MPAN is broken")

There's also a shortcut if you just want validation:

from mpan import is_valid


is_valid("2499999999991")     # True
is_valid("2499999999990")     # False
is_valid("I am not an MPAN")  # False

Installation

It's on PyPI:

$ pip install mpan

Requirements

This is a pure-python module with no external dependencies. However, you'll need to be running Python 3.8 or higher.

Development

Setting up a Local Development Environment

We're using Poetry, so if you want to make some changes, you should install that and then just run poetry install. This will pull in all the development dependencies like pytest, isort, etc.

Testing

When inside your virtualenv, just run:

$ pytest

Deployment/Releases

To build, use Poetry:

$ poetry build

To publish a new release, use Poetry for that too:

$ poetry publish

External Documentation

This is based largely on the Wikipedia article on the MPAN standard. The validation code for example is cribbed right from there.

Changelog

1.0.4

  • Minor update to the validation error message.

1.0.3

  • Bugfix: Comparing two identical MPAN objects now returns boolean True, while comparing an MPAN object to a string of the same value returns False.
  • Added lots more documentation to the README.

1.0.2

  • .is_valid() was amended to validate the top row as well.
  • is_valid() now returns a boolean rather than potentially throwing an InvalidMPANError.

1.0.1

  • Minor change to use a new contact email

1.0.0

  • Initial release

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

mpan-1.0.4.tar.gz (8.7 kB view details)

Uploaded Source

Built Distribution

mpan-1.0.4-py3-none-any.whl (7.3 kB view details)

Uploaded Python 3

File details

Details for the file mpan-1.0.4.tar.gz.

File metadata

  • Download URL: mpan-1.0.4.tar.gz
  • Upload date:
  • Size: 8.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.7 CPython/3.8.10 Linux/5.8.0-63-generic

File hashes

Hashes for mpan-1.0.4.tar.gz
Algorithm Hash digest
SHA256 e4444858f9e8522c0421e9805b180be225a3edb49ead4c1fb726bfd77c0f4b45
MD5 32488426b2eb46067ce08d11489d991d
BLAKE2b-256 bfc494903af60e0ea7d5f7d4bc354219c8a5b6b898b52703bcb8c3a82e0acbd8

See more details on using hashes here.

File details

Details for the file mpan-1.0.4-py3-none-any.whl.

File metadata

  • Download URL: mpan-1.0.4-py3-none-any.whl
  • Upload date:
  • Size: 7.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.7 CPython/3.8.10 Linux/5.8.0-63-generic

File hashes

Hashes for mpan-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 861725e9dd0e28b396d5b4ea80261a2b8cfd9126a8a369380b2f768364fa9997
MD5 d34a76b3e3c3d270fbe01da4748f4bd3
BLAKE2b-256 f95dfbba40da750abf37bcd30a8d5fba18164a2e13f233b8502533e4a5a2f34a

See more details on using hashes here.

Supported by

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