Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
soitool
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
bachelor-paa-bittet
soitool
Commits
3e9a4912
Commit
3e9a4912
authored
5 years ago
by
morkolai
Browse files
Options
Downloads
Patches
Plain Diff
#29 Laget funksjon for å legge til 1 ord og delvis testet den
parent
98e53a44
No related branches found
Branches containing commit
No related tags found
1 merge request
!15
Kodebok-koder
Pipeline
#73097
failed
5 years ago
Stage: lint
Stage: test
Stage: deploy
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
soitool/coder.py
+6
-5
6 additions, 5 deletions
soitool/coder.py
soitool/database.py
+82
-36
82 additions, 36 deletions
soitool/database.py
test/test_database.py
+34
-19
34 additions, 19 deletions
test/test_database.py
with
122 additions
and
60 deletions
soitool/coder.py
+
6
−
5
View file @
3e9a4912
"""
Generate codes.
"""
import
string
# https://realpython.com/lessons/cryptographically-secure-random-data-python/
import
secrets
def
get_code
(
length
,
mode
=
'
ascii
'
):
def
get_code
(
length
,
mode
=
"
ascii
"
):
"""
Generate a single random code.
...
...
@@ -27,9 +28,9 @@ def get_code(length, mode='ascii'):
characters
=
string
.
ascii_uppercase
if
mode
==
'
digits
'
:
if
mode
==
"
digits
"
:
characters
=
string
.
digits
elif
mode
==
'
combo
'
:
elif
mode
==
"
combo
"
:
characters
=
string
.
ascii_uppercase
+
string
.
digits
while
i
<
length
:
...
...
@@ -39,7 +40,7 @@ def get_code(length, mode='ascii'):
return
code
def
get_code_set
(
size
,
length
,
mode
=
'
ascii
'
):
def
get_code_set
(
size
,
length
,
mode
=
"
ascii
"
):
"""
Generate a set of codes.
...
...
@@ -85,7 +86,7 @@ def get_code_length(quantity):
Lenght of code
"""
length
=
0
while
len
(
string
.
ascii_uppercase
)
**
length
<
quantity
:
while
len
(
string
.
ascii_uppercase
)
**
length
<
quantity
:
length
=
length
+
1
return
length
This diff is collapsed.
Click to expand it.
soitool/database.py
+
82
−
36
View file @
3e9a4912
...
...
@@ -7,20 +7,23 @@ import schedule
import
soitool.coder
# Set name and path to (future) database
DBNAME
=
'
database
'
DBNAME
=
"
database
"
CURDIR
=
os
.
path
.
dirname
(
__file__
)
DBPATH
=
os
.
path
.
join
(
CURDIR
,
DBNAME
)
# DDL-statements for creating tables
CODEBOOK
=
'
CREATE TABLE CodeBook
'
\
'
(Word VARCHAR PRIMARY KEY, Category VARCHAR,
'
\
'
Code CHAR(3) UNIQUE, Type int DEFAULT 0)
'
CATEGORYWORDS
=
'
CREATE TABLE CategoryWords
'
\
'
(Word VARCHAR PRIMARY KEY, Category VARCHAR)
'
BYHEART
=
'
CREATE TABLE ByHeart(Word VARCHAR PRIMARY KEY)
'
class
Database
():
CODEBOOK
=
(
"
CREATE TABLE CodeBook
"
"
(Word VARCHAR PRIMARY KEY, Category VARCHAR,
"
"
Code VARCHAR UNIQUE, Type int DEFAULT 0)
"
)
CATEGORYWORDS
=
(
"
CREATE TABLE CategoryWords
"
"
(Word VARCHAR PRIMARY KEY, Category VARCHAR)
"
)
BYHEART
=
"
CREATE TABLE ByHeart(Word VARCHAR PRIMARY KEY)
"
class
Database
:
"""
Holds database-connection and related functions.
...
...
@@ -32,17 +35,17 @@ class Database():
db_exists
=
os
.
path
.
exists
(
DBPATH
)
if
db_exists
:
print
(
'
Connecting to existing DB.
'
)
print
(
"
Connecting to existing DB.
"
)
self
.
conn
=
sqlite3
.
connect
(
DBPATH
)
print
(
'
DB-connection established.
'
)
print
(
"
DB-connection established.
"
)
else
:
print
(
'
Creating new DB.
'
)
print
(
"
Creating new DB.
"
)
self
.
conn
=
sqlite3
.
connect
(
DBPATH
)
self
.
create_tables
()
print
(
'
DB created.
'
)
print
(
"
DB created.
"
)
self
.
fill_tables
()
print
(
'
Tables filled with data.
'
)
print
(
"
Tables filled with data.
"
)
self
.
conn
.
row_factory
=
sqlite3
.
Row
# Enables row['columnName']
...
...
@@ -75,19 +78,24 @@ class Database():
codes
=
soitool
.
coder
.
get_code_set
(
len
(
entries
),
entries_len
)
# Insert data in db
stmt
=
'
INSERT INTO CodeBook(Word, Category, Type, Code)
'
\
'
VALUES(?,?,?,?)
'
stmt
=
(
"
INSERT INTO CodeBook(Word, Category, Type, Code)
"
"
VALUES(?,?,?,?)
"
)
for
word
in
entries
:
self
.
conn
.
execute
(
stmt
,
(
word
[
'
word
'
],
word
[
'
category
'
],
word
[
'
type
'
],
codes
.
pop
()))
self
.
conn
.
execute
(
stmt
,
(
word
[
"
word
"
],
word
[
"
category
"
],
word
[
"
type
"
],
codes
.
pop
()),
)
def
fill_by_heart
(
self
):
"""
Read data from ByHeart.txt and fill DB-table ByHeart.
"""
file_path
=
os
.
path
.
join
(
CURDIR
,
"
testdata/ByHeart.txt
"
)
f
=
open
(
file_path
,
"
r
"
,
encoding
=
'
utf-8
'
)
f
=
open
(
file_path
,
"
r
"
,
encoding
=
"
utf-8
"
)
# Loop through words on file and insert them into ByHeart-table
stmt
=
'
INSERT INTO ByHeart(Word) VALUES(?)
'
stmt
=
"
INSERT INTO ByHeart(Word) VALUES(?)
"
for
expr
in
f
:
self
.
conn
.
execute
(
stmt
,
(
expr
.
rstrip
(),))
f
.
close
()
...
...
@@ -95,7 +103,7 @@ class Database():
def
fill_category_words
(
self
):
"""
Read data from CategoryWords.txt and fill DB-table CategoryWords.
"""
file_path
=
os
.
path
.
join
(
CURDIR
,
"
testdata/CategoryWords.txt
"
)
f
=
open
(
file_path
,
"
r
"
,
encoding
=
'
utf-8
'
)
f
=
open
(
file_path
,
"
r
"
,
encoding
=
"
utf-8
"
)
# Get number of categories on file
no_of_categories
=
int
(
f
.
readline
().
rstrip
())
...
...
@@ -108,7 +116,7 @@ class Database():
no_of_words
=
int
(
line
[
1
].
rstrip
())
# Loop through words in category and add rows to DB
stmt
=
'
INSERT INTO CategoryWords(Word, Category) VALUES(?, ?)
'
stmt
=
"
INSERT INTO CategoryWords(Word, Category) VALUES(?, ?)
"
for
_
in
range
(
no_of_words
):
word
=
f
.
readline
().
rstrip
()
self
.
conn
.
execute
(
stmt
,
(
word
,
category
,))
...
...
@@ -123,11 +131,11 @@ class Database():
List of strings
Categories
"""
stmt
=
'
SELECT DISTINCT Category FROM CategoryWords
'
stmt
=
"
SELECT DISTINCT Category FROM CategoryWords
"
queried
=
self
.
conn
.
execute
(
stmt
)
categories
=
[]
for
row
in
queried
:
categories
.
append
(
row
[
'
Category
'
])
categories
.
append
(
row
[
"
Category
"
])
return
categories
...
...
@@ -146,44 +154,82 @@ class Database():
[{
'
word
'
: str,
'
type
'
: str,
'
category
'
: str,
'
code
'
: str}]
"""
# Get either full or small codebook
stmt
=
'
SELECT * FROM CodeBook
'
stmt
=
"
SELECT * FROM CodeBook
"
if
small
:
stmt
=
stmt
+
'
WHERE Type = ?
'
stmt
=
stmt
+
"
WHERE Type = ?
"
queried
=
self
.
conn
.
execute
(
stmt
,
(
1
,)).
fetchall
()
else
:
queried
=
self
.
conn
.
execute
(
stmt
).
fetchall
()
codebook
=
[]
for
entry
in
queried
:
codebook
.
append
({
'
word
'
:
entry
[
'
Word
'
],
'
category
'
:
entry
[
'
Category
'
],
'
type
'
:
entry
[
'
Type
'
],
'
code
'
:
entry
[
'
Code
'
]})
codebook
.
append
(
{
"
word
"
:
entry
[
"
Word
"
],
"
category
"
:
entry
[
"
Category
"
],
"
type
"
:
entry
[
"
Type
"
],
"
code
"
:
entry
[
"
Code
"
],
}
)
return
codebook
def
update_codebook
(
self
):
"""
Update codes in DB.
"""
# Get all the words (PK)
stmt
=
'
SELECT Word FROM CodeBook
'
stmt
=
"
SELECT Word FROM CodeBook
"
words
=
self
.
conn
.
execute
(
stmt
).
fetchall
()
# Get number of entries
stmt
=
'
SELECT COUNT(*) FROM CodeBook
'
stmt
=
"
SELECT COUNT(*) FROM CodeBook
"
number_of_entries
=
self
.
conn
.
execute
(
stmt
).
fetchall
()[
0
][
0
]
# Generate new codes
code_len
=
soitool
.
coder
.
get_code_length
(
number_of_entries
)
codes
=
soitool
.
coder
.
get_code_set
(
number_of_entries
,
code_len
)
# Statement for update
stmt
=
'
UPDATE CodeBook SET Code = ?
WHERE Word = ?
'
stmt
=
"
UPDATE CodeBook SET Code = ?
"
# Wiping Code column because of UNIQUE
for
i
in
range
(
number_of_entries
):
self
.
conn
.
execute
(
stmt
,
(
None
,
words
[
i
][
0
]))
self
.
conn
.
execute
(
stmt
,
(
None
,))
# Fill Code column with new codes
stmt
=
stmt
+
"
WHERE Word = ?
"
for
i
in
range
(
number_of_entries
):
self
.
conn
.
execute
(
stmt
,
(
codes
.
pop
(),
words
[
i
][
0
]))
print
(
"
Code in CodeBook updated
"
)
def
add_code
(
self
,
word
,
mode
=
"
ascii
"
):
"""
Add a code to the new word.
Parameters
----------
word : string
The word to generate a code for.
mode : string
'
ascii
'
for letters (default),
'
digits
'
for digits and
'
combo
'
for combination of letters and digits.
"""
# Get length of codes
stmt
=
"
SELECT COUNT(*) FROM CodeBook
"
number_of_entries
=
self
.
conn
.
execute
(
stmt
).
fetchall
()[
0
][
0
]
# TODO ordet ligger alt inne så her er det feil
code_len
=
soitool
.
coder
.
get_code_length
(
number_of_entries
)
# If adding a word makes the code longer, update whole CodeBook in db
if
code_len
<
soitool
.
coder
.
get_code_length
(
number_of_entries
+
1
):
self
.
update_codebook
()
else
:
# Get all the used codes
stmt
=
"
SELECT Code FROM CodeBook
"
codes_li
=
self
.
conn
.
execute
(
stmt
).
fetchall
()
codes_set
=
set
([
i
[:][
0
]
for
i
in
codes_li
])
# Get new unique code
code
=
soitool
.
coder
.
get_code
(
code_len
,
mode
)
while
code
in
codes_set
:
code
=
soitool
.
coder
.
get_code
(
code_len
,
mode
)
# Update db with new code
stmt
=
"
UPDATE CodeBook SET Code = ? WHERE Word = ?
"
self
.
conn
.
execute
(
stmt
,
(
code
,
word
))
def
update_codebook_auto
(
self
,
clock
):
"""
Update DB every day at clock.
...
...
This diff is collapsed.
Click to expand it.
test/test_database.py
+
34
−
19
View file @
3e9a4912
...
...
@@ -32,7 +32,7 @@ class DatabaseTest(unittest.TestCase):
no_of_expr
=
len
(
expressions
)
# Retrieve expressions from DB:
stmt
=
'
SELECT * FROM ByHeart
'
stmt
=
"
SELECT * FROM ByHeart
"
queried
=
self
.
database
.
conn
.
execute
(
stmt
).
fetchall
()
# Assert equal amount of expressions in table and file
...
...
@@ -73,7 +73,7 @@ class DatabaseTest(unittest.TestCase):
self
.
assertEqual
(
categories_db
,
categories_file
)
# Retrieve data from DB
stmt
=
'
SELECT * FROM CategoryWords
'
stmt
=
"
SELECT * FROM CategoryWords
"
queried
=
self
.
database
.
conn
.
execute
(
stmt
).
fetchall
()
# Assert equal categories in table and file
...
...
@@ -89,7 +89,7 @@ class DatabaseTest(unittest.TestCase):
file
.
close
()
# Get data from db
stmt
=
'
SELECT * FROM CodeBook
'
stmt
=
"
SELECT * FROM CodeBook
"
actual
=
self
.
database
.
conn
.
execute
(
stmt
).
fetchall
()
# Check same lenght
...
...
@@ -100,10 +100,10 @@ class DatabaseTest(unittest.TestCase):
# Check equality
for
i
,
entry
in
enumerate
(
expected
):
self
.
assertEqual
(
entry
[
'
word
'
],
actual
[
i
][
0
])
self
.
assertEqual
(
entry
[
'
category
'
],
actual
[
i
][
1
])
self
.
assertEqual
(
entry
[
"
word
"
],
actual
[
i
][
0
])
self
.
assertEqual
(
entry
[
"
category
"
],
actual
[
i
][
1
])
self
.
assertRegex
(
actual
[
i
][
2
],
"
[A-Z]{
"
+
str
(
code_len
)
+
"
}
"
)
self
.
assertEqual
(
entry
[
'
type
'
],
actual
[
i
][
3
])
self
.
assertEqual
(
entry
[
"
type
"
],
actual
[
i
][
3
])
def
test_get_categories
(
self
):
"""
Assert function get_categories works as expected.
"""
...
...
@@ -145,10 +145,10 @@ class DatabaseTest(unittest.TestCase):
# Compare contents
for
i
,
entry
in
enumerate
(
expected
):
self
.
assertEqual
(
entry
[
'
word
'
],
actual
[
i
][
'
word
'
])
self
.
assertEqual
(
entry
[
'
category
'
],
actual
[
i
][
'
category
'
])
self
.
assertRegex
(
actual
[
i
][
'
code
'
],
"
[A-Z]{
"
+
str
(
code_len
)
+
"
}
"
)
self
.
assertEqual
(
entry
[
'
type
'
],
actual
[
i
][
'
type
'
])
self
.
assertEqual
(
entry
[
"
word
"
],
actual
[
i
][
"
word
"
])
self
.
assertEqual
(
entry
[
"
category
"
],
actual
[
i
][
"
category
"
])
self
.
assertRegex
(
actual
[
i
][
"
code
"
],
"
[A-Z]{
"
+
str
(
code_len
)
+
"
}
"
)
self
.
assertEqual
(
entry
[
"
type
"
],
actual
[
i
][
"
type
"
])
def
test_get_codebook_small
(
self
):
"""
Assert function get_codebook only return the small codebook.
"""
...
...
@@ -161,7 +161,7 @@ class DatabaseTest(unittest.TestCase):
# Fill expected with only small codebook entries
expected
=
[]
for
entry
in
data
:
if
entry
[
'
type
'
]
==
1
:
if
entry
[
"
type
"
]
==
1
:
expected
.
append
(
entry
)
# Get small codebook from db
...
...
@@ -175,29 +175,44 @@ class DatabaseTest(unittest.TestCase):
# Compare contents
for
i
,
entry
in
enumerate
(
expected
):
self
.
assertEqual
(
entry
[
'
word
'
],
actual
[
i
][
'
word
'
])
self
.
assertEqual
(
entry
[
'
category
'
],
actual
[
i
][
'
category
'
])
self
.
assertRegex
(
actual
[
i
][
'
code
'
],
"
[A-Z]{
"
+
str
(
code_len
)
+
"
}
"
)
self
.
assertEqual
(
entry
[
'
type
'
],
actual
[
i
][
'
type
'
])
self
.
assertEqual
(
entry
[
"
word
"
],
actual
[
i
][
"
word
"
])
self
.
assertEqual
(
entry
[
"
category
"
],
actual
[
i
][
"
category
"
])
self
.
assertRegex
(
actual
[
i
][
"
code
"
],
"
[A-Z]{
"
+
str
(
code_len
)
+
"
}
"
)
self
.
assertEqual
(
entry
[
"
type
"
],
actual
[
i
][
"
type
"
])
def
test_update_codebook
(
self
):
"""
Test that the codes get updated.
"""
# Get number of entries
stmt
=
'
SELECT COUNT(*) FROM CodeBook ORDER BY Word
'
stmt
=
"
SELECT COUNT(*) FROM CodeBook ORDER BY Word
"
number_of_entries
=
self
.
database
.
conn
.
execute
(
stmt
).
fetchall
()[
0
][
0
]
# Get old and updated word-code combinations
stmt
=
'
SELECT Word, Code FROM CodeBook
'
stmt
=
"
SELECT Word, Code FROM CodeBook
"
old
=
self
.
database
.
conn
.
execute
(
stmt
).
fetchall
()
self
.
database
.
update_codebook
()
updated
=
self
.
database
.
conn
.
execute
(
stmt
).
fetchall
()
# Collect approximately score of not updated pairs
pairs
=
0
for
i
in
range
(
0
,
number_of_entries
,
2
):
if
old
[
i
][
'
Code
'
]
==
updated
[
i
][
'
Code
'
]:
if
old
[
i
][
"
Code
"
]
==
updated
[
i
][
"
Code
"
]:
pairs
=
pairs
+
1
# Test that at least some of the test are new
self
.
assertTrue
(
pairs
<
number_of_entries
)
def
test_add_code
(
self
):
"""
Test add a single code to CodeBook
"""
testdata
=
(
"
testword
"
,
"
testcategory
"
)
stmt
=
"
INSERT INTO CodeBook (Word, Category) VALUES (?,?)
"
self
.
database
.
conn
.
execute
(
stmt
,
(
testdata
[
0
],
testdata
[
1
]))
self
.
database
.
add_code
(
testdata
[
0
])
stmt
=
"
SELECT Code FROM CodeBook WHERE Word = ?
"
code
=
self
.
database
.
conn
.
execute
(
stmt
,
(
testdata
[
0
],)).
fetchall
()[
0
][
0
]
self
.
assertRegex
(
code
,
"
[A-Z0-9]
"
)
if
__name__
==
'
__main__
'
:
def
test_add_code_extending_code_length
(
self
):
"""
Test all codes get updated when code lenght i changed.
"""
if
__name__
==
"
__main__
"
:
unittest
.
main
()
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment