Skip to content

Commit eef6e74

Browse files
Merge pull request #10 from codonlibrary/subbranch_more-functions
Subbranch more functions
2 parents 5cd660a + c988578 commit eef6e74

6 files changed

Lines changed: 150 additions & 3 deletions

File tree

.travis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
language: python
22
python:
33
- 3.5
4+
install:
5+
- pip install -r requirements.txt
46
script:
57
- pytest

codonPython/dateValidator.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import re
2+
3+
4+
def validDate(date_string: str)->bool:
5+
"""
6+
Validates stringtype dates of type `dd/mm/yyyy`, `dd-mm-yyyy` or `dd.mm.yyyy` from
7+
years 1900-9999. Leap year support included.
8+
9+
Parameters
10+
----------
11+
date_string : str
12+
Date to be validated
13+
14+
Returns
15+
----------
16+
boolean
17+
Whether the date is valid or not
18+
19+
Examples
20+
---------
21+
>>> validDate("11/02/1996")
22+
True
23+
>>> validDate("29/02/2016")
24+
True
25+
>>> validDate("43/01/1996")
26+
False
27+
"""
28+
29+
# This regex string will validate dates of type `dd/mm/yyyy`, `dd-mm-yyyy` or `dd.mm.yyyy`
30+
# from years 1900 - 9999. Leap year support included. Regex string from
31+
# https://stackoverflow.com/questions/15491894/regex-to-validate-date-format-dd-mm-yyyy
32+
if re.match(r"^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:19|[2-9]\d)?\d{2})$", date_string, flags=0):
33+
return True
34+
else:
35+
return False

codonPython/nhsNumberGenerator.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import random
2+
3+
4+
def nhsNumberGenerator(to_generate: int)->list:
5+
"""
6+
Generates random NHS number(s) compliant with modulus 11 checks recorded
7+
in the data dictonary.
8+
https://www.datadictionary.nhs.uk/data_dictionary/attributes/n/nhs/nhs_number_de.asp?shownav=1
9+
10+
Parameters
11+
----------
12+
to_generate : int
13+
number of NHS numbers to generate
14+
15+
Returns
16+
----------
17+
generated : list
18+
List of randomly generated NHS numbers
19+
20+
Examples
21+
---------
22+
>>> random.seed(42)
23+
>>> nhsNumberGenerator(2)
24+
[7865793030, 1933498560]
25+
"""
26+
27+
generated = []
28+
while len(generated) < to_generate:
29+
# Random 9 digit number starting with non-zero digit
30+
number = random.randint(100000000, 999999999)
31+
digits = [int(digit) for digit in str(number)]
32+
# Apply weighting to digits
33+
weighted_digits = [(10 - index) * digit for (index, digit) in enumerate(digits)]
34+
# Sum of all weighted digits must be a multiple of 11 to be valid.
35+
if sum(weighted_digits) % 11 == 0:
36+
# Add check digit to valid number
37+
number = int(str(number) + "0")
38+
generated.append(number)
39+
return generated

codonPython/tableFromSql.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import sqlalchemy
2+
from sqlalchemy import create_engine
3+
import pandas as pd
4+
5+
6+
def tableFromSql(server: str, database: str, table_name: str, user: str = "", password: str = "", schema: str = None, index_col: str = None, coerce_float: bool = True, parse_dates: list = None, columns: list = None, chunksize: int = None):
7+
'''
8+
Returns a SQL table in a DataFrame.
9+
10+
Convert a table stored in SQL Server 2016 into a pandas dataframe.
11+
Uses sqlalchemy and pandas.
12+
13+
Parameters
14+
----------
15+
server : string
16+
Name of the SQL server
17+
database : string
18+
Name of the SQL database
19+
user : string, default: ""
20+
If verification is required, name of the user
21+
password : string, default: ""
22+
If verification is required, password of the user
23+
table_name : string
24+
Name of SQL table in database.
25+
schema : string, default : None
26+
Name of SQL schema in database to query (if database flavor supports this). Uses
27+
default schema if None (default).
28+
index_col : string or list of strings, default : None
29+
Column(s) to set as index(MultiIndex).
30+
coerce_float : boolean, default : True
31+
Attempts to convert values of non-string, non-numeric objects (like decimal.Decimal)
32+
to floating point. Can result in loss of Precision.
33+
parse_dates : list or dict, default : None
34+
- List of column names to parse as dates.
35+
- Dict of {column_name: format string} where format string is strftime compatible in
36+
case of parsing string times or is one of (D, s, ns, ms, us) in case of parsing
37+
integer timestamps.
38+
- Dict of {column_name: arg dict}, where the arg dict corresponds to the keyword
39+
arguments of pandas.to_datetime() Especially useful with databases without native
40+
Datetime support, such as SQLite.
41+
columns : list, default : None
42+
List of column names to select from SQL table
43+
chunksize : int, default : None
44+
If specified, returns an iterator where chunksize is the number of rows to include
45+
in each chunk.
46+
47+
Returns
48+
----------
49+
pd.DataFrame
50+
Dataframe of the table requested from sql server
51+
52+
Examples
53+
---------
54+
# >>> tableFromSql("myServer2", "myDatabase2", "myTable2")
55+
# pd.DataFrame
56+
# >>> tableFromSql("myServer", "myDatabase", "myTable", schema="specialSchema", columns=["col_1", "col_3"])
57+
# pd.DataFrame
58+
'''
59+
60+
try:
61+
uri = "mssql+pyodbc://{}:{}@{}/{}?driver=SQL Server Native Client 11.0".format(user, password, server, database)
62+
engine = create_engine(uri)
63+
return pd.read_sql_table(table_name, engine, schema=schema, index_col=index_col, coerce_float=coerce_float, parse_dates=parse_dates, columns=columns, chunksize=chunksize)
64+
except Exception as error:
65+
raise error
66+

requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
numpy>=1.16.0
2+
scipy>=0.19.0
3+
pandas>=0.24.0
4+
sqlalchemy>=1.3.5

setup.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from setuptools import setup, find_packages
22

3+
with open('requirements.txt') as f:
4+
requirements = f.read().splitlines()
5+
36
setup(
47
name='codonPython',
58
version='0.1',
69
license='BSD',
710
packages=['codonPython',],
8-
install_required=[
9-
'numpy',
10-
],
11+
install_requires=requirements,
1112
author='NHS Digital DIS Team',
1213
author_email='paul.ellingham@nhs.net',
1314
url='https://digital.nhs.uk/data-and-information',

0 commit comments

Comments
 (0)