<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/pysim/+/23593">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">card_key_provider: Documentation with sphinx / autodoc<br><br>Change-Id: Ia41e14d643d452d92fc8d3c2fb9c4ac9021402e9<br>---<br>M docs/library.rst<br>M pySim/card_key_provider.py<br>2 files changed, 71 insertions(+), 15 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/93/23593/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/docs/library.rst b/docs/library.rst</span><br><span>index ae027ff..656a780 100644</span><br><span>--- a/docs/library.rst</span><br><span>+++ b/docs/library.rst</span><br><span>@@ -90,3 +90,9 @@</span><br><span> </span><br><span> .. automodule:: pySim.card_handler</span><br><span> :members:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+pySim card_key_provider</span><br><span style="color: hsl(120, 100%, 40%);">+-----------------------</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+.. automodule:: pySim.card_key_provider</span><br><span style="color: hsl(120, 100%, 40%);">+ :members:</span><br><span>diff --git a/pySim/card_key_provider.py b/pySim/card_key_provider.py</span><br><span>index 80f93d0..b4e1daa 100644</span><br><span>--- a/pySim/card_key_provider.py</span><br><span>+++ b/pySim/card_key_provider.py</span><br><span>@@ -1,5 +1,14 @@</span><br><span> # coding=utf-8</span><br><span style="color: hsl(0, 100%, 40%);">-"""Abstraction of card related data that can be queried from external source."""</span><br><span style="color: hsl(120, 100%, 40%);">+"""Obtaining card parameters (mostly key data) from external source.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This module contains a base class and a concrete implementation of</span><br><span style="color: hsl(120, 100%, 40%);">+obtaining card key material (or other card-individual parameters) from</span><br><span style="color: hsl(120, 100%, 40%);">+an external data source.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This is used e.g. to keep PIN/PUK data in some file on disk, avoiding</span><br><span style="color: hsl(120, 100%, 40%);">+the need of manually entering the related card-individual data on every</span><br><span style="color: hsl(120, 100%, 40%);">+operation with pySim-shell.</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span> </span><br><span> # (C) 2021 by Sysmocom s.f.m.c. GmbH</span><br><span> # All Rights Reserved</span><br><span>@@ -23,16 +32,24 @@</span><br><span> </span><br><span> import csv</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-card_key_providers = List[CardKeyProvider]</span><br><span style="color: hsl(120, 100%, 40%);">+card_key_providers = List['CardKeyProvider']</span><br><span> </span><br><span> class CardKeyProvider(object):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Abstract base class, not containing any concrete implementation."""</span><br><span> </span><br><span> VALID_FIELD_NAMES = ['ICCID', 'ADM1', 'IMSI', 'PIN1', 'PIN2', 'PUK1', 'PUK2']</span><br><span> </span><br><span> # check input parameters, but do nothing concrete yet</span><br><span style="color: hsl(0, 100%, 40%);">- def get_data(self, fields:List[str]=[], key:str='ICCID', value:str="") -> Dict[str,str]:</span><br><span style="color: hsl(0, 100%, 40%);">- """abstract implementation of get_data that only verifies the function parameters"""</span><br><span style="color: hsl(120, 100%, 40%);">+ def _verify_get_data(self, fields:List[str]=[], key:str='ICCID', value:str="") -> Dict[str,str]:</span><br><span style="color: hsl(120, 100%, 40%);">+ """Verify multiple fields for identified card.</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ Args:</span><br><span style="color: hsl(120, 100%, 40%);">+ fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained</span><br><span style="color: hsl(120, 100%, 40%);">+ key : look-up key to identify card data, such as 'ICCID'</span><br><span style="color: hsl(120, 100%, 40%);">+ value : value for look-up key to identify card data</span><br><span style="color: hsl(120, 100%, 40%);">+ Returns:</span><br><span style="color: hsl(120, 100%, 40%);">+ dictionary of {field, value} strings for each requested field from 'fields'</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span> for f in fields:</span><br><span> if (f not in self.VALID_FIELD_NAMES):</span><br><span> raise ValueError("Requested field name '%s' is not a valid field name, valid field names are: %s" %</span><br><span>@@ -51,23 +68,34 @@</span><br><span> return result.get(field)</span><br><span> </span><br><span> def get(self, fields:List[str], key:str, value:str) -> Dict[str,str]:</span><br><span style="color: hsl(0, 100%, 40%);">- """get fields from CSV file using a specified key/value pair"""</span><br><span style="color: hsl(120, 100%, 40%);">+ """Get multiple card-individual fields for identified card.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ Args:</span><br><span style="color: hsl(120, 100%, 40%);">+ fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained</span><br><span style="color: hsl(120, 100%, 40%);">+ key : look-up key to identify card data, such as 'ICCID'</span><br><span style="color: hsl(120, 100%, 40%);">+ value : value for look-up key to identify card data</span><br><span style="color: hsl(120, 100%, 40%);">+ Returns:</span><br><span style="color: hsl(120, 100%, 40%);">+ dictionary of {field, value} strings for each requested field from 'fields'</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span> pass</span><br><span> </span><br><span> class CardKeyProviderCsv(CardKeyProvider):</span><br><span style="color: hsl(0, 100%, 40%);">- """card data class that allows the user to query against a specified CSV file"""</span><br><span style="color: hsl(120, 100%, 40%);">+ """Card key provider implementation that allows to query against a specified CSV file"""</span><br><span> csv_file = None</span><br><span> filename = None</span><br><span> </span><br><span> def __init__(self, filename:str):</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span style="color: hsl(120, 100%, 40%);">+ Args:</span><br><span style="color: hsl(120, 100%, 40%);">+ filename : file name (path) of CSV file containing card-individual key/data</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span> self.csv_file = open(filename, 'r')</span><br><span> if not self.csv_file:</span><br><span style="color: hsl(0, 100%, 40%);">- raise RuntimeError("Could not open CSV-File '%s'" % filename)</span><br><span style="color: hsl(120, 100%, 40%);">+ raise RuntimeError("Could not open CSV file '%s'" % filename)</span><br><span> self.filename = filename</span><br><span> </span><br><span> def get(self, fields:List[str], key:str, value:str) -> Dict[str,str]:</span><br><span style="color: hsl(0, 100%, 40%);">- """get fields from CSV file using a specified key/value pair"""</span><br><span style="color: hsl(0, 100%, 40%);">- super().get_data(fields, key, value)</span><br><span style="color: hsl(120, 100%, 40%);">+ super()._verify_get_data(fields, key, value)</span><br><span> </span><br><span> self.csv_file.seek(0)</span><br><span> cr = csv.DictReader(self.csv_file)</span><br><span>@@ -88,17 +116,31 @@</span><br><span> </span><br><span> </span><br><span> def card_key_provider_register(provider:CardKeyProvider, provider_list=card_key_providers):</span><br><span style="color: hsl(0, 100%, 40%);">- """Register a new card data provider"""</span><br><span style="color: hsl(120, 100%, 40%);">+ """Register a new card key provider.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ Args:</span><br><span style="color: hsl(120, 100%, 40%);">+ provider : the to-be-registered provider</span><br><span style="color: hsl(120, 100%, 40%);">+ provider_list : override the list of providers from the global default</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span> if not isinstance(provider, CardKeyProvider):</span><br><span> raise ValueError("provider is not a card data provier")</span><br><span> provider_list.append(provider)</span><br><span> </span><br><span> </span><br><span> def card_key_provider_get(fields, key:str, value:str, provider_list=card_key_providers) -> Dict[str,str]:</span><br><span style="color: hsl(0, 100%, 40%);">- """Query all registered card data providers"""</span><br><span style="color: hsl(120, 100%, 40%);">+ """Query all registered card data providers for card-individual [key] data.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ Args:</span><br><span style="color: hsl(120, 100%, 40%);">+ fields : list of valid field names such as 'ADM1', 'PIN1', ... which are to be obtained</span><br><span style="color: hsl(120, 100%, 40%);">+ key : look-up key to identify card data, such as 'ICCID'</span><br><span style="color: hsl(120, 100%, 40%);">+ value : value for look-up key to identify card data</span><br><span style="color: hsl(120, 100%, 40%);">+ provider_list : override the list of providers from the global default</span><br><span style="color: hsl(120, 100%, 40%);">+ Returns:</span><br><span style="color: hsl(120, 100%, 40%);">+ dictionary of {field, value} strings for each requested field from 'fields'</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span> for p in provider_list:</span><br><span> if not isinstance(p, CardKeyProvider):</span><br><span style="color: hsl(0, 100%, 40%);">- raise ValueError("provider list contains provider, which is not a card data provier")</span><br><span style="color: hsl(120, 100%, 40%);">+ raise ValueError("provider list contains element which is not a card data provier")</span><br><span> result = p.get(fields, key, value)</span><br><span> if result:</span><br><span> return result</span><br><span>@@ -106,12 +148,20 @@</span><br><span> </span><br><span> </span><br><span> def card_key_provider_get_field(field:str, key:str, value:str, provider_list=card_key_providers) -> Optional[str]:</span><br><span style="color: hsl(0, 100%, 40%);">- """Query all registered card data providers for a single field"""</span><br><span style="color: hsl(120, 100%, 40%);">+ """Query all registered card data providers for a single field.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ Args:</span><br><span style="color: hsl(120, 100%, 40%);">+ field : name valid field such as 'ADM1', 'PIN1', ... which is to be obtained</span><br><span style="color: hsl(120, 100%, 40%);">+ key : look-up key to identify card data, such as 'ICCID'</span><br><span style="color: hsl(120, 100%, 40%);">+ value : value for look-up key to identify card data</span><br><span style="color: hsl(120, 100%, 40%);">+ provider_list : override the list of providers from the global default</span><br><span style="color: hsl(120, 100%, 40%);">+ Returns:</span><br><span style="color: hsl(120, 100%, 40%);">+ dictionary of {field, value} strings for the requested field</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span> for p in provider_list:</span><br><span> if not isinstance(p, CardKeyProvider):</span><br><span style="color: hsl(0, 100%, 40%);">- raise ValueError("provider list contains provider, which is not a card data provier")</span><br><span style="color: hsl(120, 100%, 40%);">+ raise ValueError("provider list contains element which is not a card data provier")</span><br><span> result = p.get_field(field, key, value)</span><br><span> if result:</span><br><span> return result</span><br><span> return None</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/pysim/+/23593">change 23593</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/pysim/+/23593"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: pysim </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ia41e14d643d452d92fc8d3c2fb9c4ac9021402e9 </div>
<div style="display:none"> Gerrit-Change-Number: 23593 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>