Compare commits
43 Commits
Author | SHA1 | Date | |
---|---|---|---|
eaac3d8e0d | |||
7478e0fc78 | |||
939a72c21e | |||
7bfca82f33 | |||
58b4c6e116 | |||
![]() |
61e8c85bbe | ||
![]() |
dac83ccbf9 | ||
![]() |
4d2b58b744 | ||
6db74b04f5 | |||
060c235e3f | |||
![]() |
ea14cde427 | ||
![]() |
fec0969d7f | ||
![]() |
af36c44e66 | ||
b913b2cb01 | |||
![]() |
37cbae2683 | ||
![]() |
14d3064309 | ||
![]() |
fd50a8628c | ||
d4165b0582 | |||
69338434ac | |||
c0a7704db8 | |||
1aa5d6f2cc | |||
![]() |
0b864dfee9 | ||
a758f26285 | |||
![]() |
f421a8abd6 | ||
e3d5c7c7a7 | |||
1d52a1dabb | |||
1fdfb491cf | |||
![]() |
0c76dc11d7 | ||
![]() |
965ede729c | ||
![]() |
432e73375a | ||
![]() |
6eccf95cf8 | ||
![]() |
3607e2ef69 | ||
b655926202 | |||
0d63af7bbc | |||
b94e080c96 | |||
31915dc7d6 | |||
dceb2d7730 | |||
504013d890 | |||
65eb1436d6 | |||
e2676beee0 | |||
3963f98baa | |||
![]() |
c01833f411 | ||
![]() |
f7110aa125 |
12
Readme.md
12
Readme.md
@@ -25,8 +25,12 @@ CC-BY-SA Olli Graf
|
|||||||
|18 | Generatoren und list comprehension|
|
|18 | Generatoren und list comprehension|
|
||||||
|19 | Webseiten (Flask)|
|
|19 | Webseiten (Flask)|
|
||||||
|20 | virtuelle Umgebungen|
|
|20 | virtuelle Umgebungen|
|
||||||
|22 | Numpy|
|
|21 | Interrupts & Signale|
|
||||||
|21 | Matplotlib|
|
|22 | NumPy|
|
||||||
|23 | Pandas|
|
|23 | MatPlotLib|
|
||||||
|
|24 | match|
|
||||||
|
|25 | reguläre Ausdrücke|
|
||||||
|
|26 | lambda Funktionen|
|
||||||
|
|27 | logging.config|
|
||||||
|
|28 | Decorators|
|
||||||
|
|
||||||
|
26
argparse/action.py
Executable file
26
argparse/action.py
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
def do_test():
|
||||||
|
print('do_test()')
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(prog='action',description='Demonstration der Action',epilog='Ende der Hilfe')
|
||||||
|
|
||||||
|
parser.add_argument('--update',help='update Hilfe')
|
||||||
|
parser.add_argument('--dry-run',help='dry-run Hilfe')
|
||||||
|
parser.add_argument('--verbose','-v', action='count')
|
||||||
|
parser.add_argument('--true', action='store_true')
|
||||||
|
parser.add_argument('-append', action='append', nargs=1)
|
||||||
|
parser.add_argument('--false', action='store_false')
|
||||||
|
parser.add_argument('--store', action='store')
|
||||||
|
parser.add_argument('--const', action = 'store_const', const=19)
|
||||||
|
|
||||||
|
parser.add_argument('--delete', action = argparse.BooleanOptionalAction)
|
||||||
|
#parser.add_argument('--no-delete', action = argparse.BooleanOptionalAction)
|
||||||
|
|
||||||
|
|
||||||
|
args=parser.parse_args()
|
||||||
|
print(f'args={args}')
|
||||||
|
print(f'verbose={args.verbose}')
|
||||||
|
|
11
argparse/help.py
Executable file
11
argparse/help.py
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(prog='HILFE',description='Demonstration der Hilfeseite',epilog='Ende der Hilfe im Epilog')
|
||||||
|
|
||||||
|
parser.add_argument('--update',help='update Hilfe')
|
||||||
|
parser.add_argument('--dry-run',help='dry-run Hilfe')
|
||||||
|
|
||||||
|
args=parser.parse_args()
|
||||||
|
|
3
camera/.gitignore
vendored
Normal file
3
camera/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
bin
|
||||||
|
lib
|
||||||
|
*.jpg
|
35
camera/pistill.py
Executable file
35
camera/pistill.py
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from picamera2 import Picamera2
|
||||||
|
from libcamera import controls
|
||||||
|
from time import sleep
|
||||||
|
import sys
|
||||||
|
|
||||||
|
to_file=''
|
||||||
|
picam = Picamera2()
|
||||||
|
|
||||||
|
def take_still(filename):
|
||||||
|
config = picam.create_preview_configuration()
|
||||||
|
picam.configure(config)
|
||||||
|
|
||||||
|
picam.start()
|
||||||
|
picam.set_controls({"AfMode": controls.AfModeEnum.Continuous})
|
||||||
|
sleep(5)
|
||||||
|
picam.capture_file(filename)
|
||||||
|
picam.close()
|
||||||
|
|
||||||
|
def parseArgs(argv):
|
||||||
|
global to_file
|
||||||
|
count = 0
|
||||||
|
for arg in argv:
|
||||||
|
if arg == '-o':
|
||||||
|
to_file = argv[count+1]
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
if __name__ =='__main__':
|
||||||
|
parseArgs(sys.argv)
|
||||||
|
print(f'to_file={to_file}')
|
||||||
|
take_still(to_file)
|
||||||
|
|
||||||
|
|
BIN
camera/test-python.jpg
Normal file
BIN
camera/test-python.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
15
camera/testcam.py
Normal file
15
camera/testcam.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from picamera2 import Picamera2
|
||||||
|
from libcamera import controls
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
picam = Picamera2()
|
||||||
|
|
||||||
|
config = picam.create_preview_configuration()
|
||||||
|
picam.configure(config)
|
||||||
|
|
||||||
|
picam.start()
|
||||||
|
picam.set_controls({"AfMode": controls.AfModeEnum.Continuous})
|
||||||
|
sleep(2)
|
||||||
|
picam.capture_file("/tank/cameratests/terri/test-python.jpg")
|
||||||
|
|
||||||
|
picam.close()
|
52
date_diff.py
Executable file
52
date_diff.py
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def date_diff_in_days(date1, date2):
|
||||||
|
try:
|
||||||
|
# Konvertiere die übergebenen Datumsangaben in datetime-Objekte
|
||||||
|
if date1 == '$today':
|
||||||
|
print('date1 ist heutiges Datum')
|
||||||
|
date1_obj = datetime.today()
|
||||||
|
date1_obj = date1_obj.replace(hour=0,minute=0,second=0,microsecond=0)
|
||||||
|
else:
|
||||||
|
print(f'konvertiere erstes Datum {date1}')
|
||||||
|
date1_obj = datetime.strptime(date1, "%d.%m.%Y")
|
||||||
|
|
||||||
|
if date2 == '$today':
|
||||||
|
print('date2 ist heutiges Datum')
|
||||||
|
date2_obj = datetime.today()
|
||||||
|
date2_obj = date2_obj.replace(hour=0,minute=0,second=0,microsecond=0)
|
||||||
|
else:
|
||||||
|
print(f'konvertiere zweites Datum {date2}')
|
||||||
|
date2_obj = datetime.strptime(date2, "%d.%m.%Y")
|
||||||
|
|
||||||
|
print(f'konvertiere zweites Datum {date2}')
|
||||||
|
|
||||||
|
|
||||||
|
# Berechne die Differenz zwischen den beiden Datumsangaben
|
||||||
|
print(f'erstes Datum: {date1_obj}, zweites Datum: {date2_obj}')
|
||||||
|
diff = abs(date1_obj - date2_obj).days
|
||||||
|
return diff
|
||||||
|
except ValueError as e:
|
||||||
|
print("Fehler beim Parsen der Datumsangaben:", e)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Überprüfe, ob genau zwei Datumsangaben als Parameter übergeben wurden
|
||||||
|
print(f'Params: {sys.argv}')
|
||||||
|
print(f'Anzahl Param: {len(sys.argv)}')
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("Bitte geben Sie zwei Datumsangaben im Format YYYY-MM-DD als Kommandozeilenparameter ein.")
|
||||||
|
else:
|
||||||
|
date1 = sys.argv[1]
|
||||||
|
date2 = sys.argv[2]
|
||||||
|
|
||||||
|
# Berechne die Differenz in Tagen zwischen den beiden Datumsangaben
|
||||||
|
difference = date_diff_in_days(date1, date2)
|
||||||
|
if difference is not None:
|
||||||
|
if sys.argv[1] == '$today':
|
||||||
|
date1= 'heutigen Tag'
|
||||||
|
if sys.argv[2] == '$today':
|
||||||
|
date2= 'heutigen Tag'
|
||||||
|
print(f"Zwischen dem {date1} und dem {date2} liegen {difference} Tage.")
|
22
docker/Dockerfile
Normal file
22
docker/Dockerfile
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Python Basis-Image
|
||||||
|
FROM python:3.11-alpine
|
||||||
|
|
||||||
|
# Arbeitsverzeichnis innerhalb des Containers
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Anwendungsabhängigkeiten in das Container-Image kopieren
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
# Abhängigkeiten installieren
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Port der Flask-Anwendung
|
||||||
|
EXPOSE 8085
|
||||||
|
|
||||||
|
# eigenen Code in das Container-Image kopieren
|
||||||
|
COPY fib/*.py /app/
|
||||||
|
COPY fib/static /app/static
|
||||||
|
COPY fib/templates /app/templates
|
||||||
|
|
||||||
|
# Befehl, der die Anwendung startet
|
||||||
|
CMD ["python", "/app/app.py"]
|
9
docker/docker-compose.yml
Normal file
9
docker/docker-compose.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
version: "2.1"
|
||||||
|
services:
|
||||||
|
fibserver:
|
||||||
|
image: hans:5000/fibserver:1
|
||||||
|
container_name: fibserver
|
||||||
|
ports:
|
||||||
|
- 8085:8085
|
||||||
|
restart: unless-stopped
|
45
docker/fib/app.py
Normal file
45
docker/fib/app.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
from flask import Flask,render_template,request
|
||||||
|
from fib_gen import fib_generator
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logging.basicConfig( format='%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s', level=logging.DEBUG)
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
return render_template('index.html')
|
||||||
|
|
||||||
|
@app.route('/fib',methods=['GET','POST'])
|
||||||
|
def fib():
|
||||||
|
fibg = fib_generator()
|
||||||
|
result = ''
|
||||||
|
logging.debug(f'request.method={request.method}')
|
||||||
|
if request.method == 'POST':
|
||||||
|
element = request.form['element']
|
||||||
|
|
||||||
|
logging.debug(f'berechne Element:{element}')
|
||||||
|
|
||||||
|
n= int(element)
|
||||||
|
#formel= str(n-2) + '+' + str(n-1)
|
||||||
|
formel = '' # Berechnungsformel initialisieren.
|
||||||
|
if element != None:
|
||||||
|
for i in range(n+1):
|
||||||
|
fib = next(fibg)
|
||||||
|
if i == n-2: # fib(n-2) zur Berechnungsformel dazu
|
||||||
|
|
||||||
|
formel += str(fib)
|
||||||
|
if i == n-1: # fib(n-1) mit + Zeichen zur Berechnungsformel dazu
|
||||||
|
formel += '+' + str(fib)
|
||||||
|
|
||||||
|
logging.debug(f'Fibonacci-Zahl: {fib}')
|
||||||
|
logging.debug(f'formel={formel}')
|
||||||
|
result=str(fib)
|
||||||
|
elif request.method == 'GET':
|
||||||
|
logging.debug('GET-Request')
|
||||||
|
return render_template('index.html', result=result,formel=formel)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0',port=8085, debug=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
12
docker/fib/fib_gen.py
Normal file
12
docker/fib/fib_gen.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
def fib_generator():
|
||||||
|
a,b = 0,1
|
||||||
|
|
||||||
|
while True:
|
||||||
|
yield a
|
||||||
|
a,b = b, a+b
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
427
docker/fib/static/css/normalize.css
vendored
Normal file
427
docker/fib/static/css/normalize.css
vendored
Normal file
@@ -0,0 +1,427 @@
|
|||||||
|
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Set default font family to sans-serif.
|
||||||
|
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||||
|
* user zoom.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: sans-serif; /* 1 */
|
||||||
|
-ms-text-size-adjust: 100%; /* 2 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove default margin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HTML5 display definitions
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct `block` display not defined for any HTML5 element in IE 8/9.
|
||||||
|
* Correct `block` display not defined for `details` or `summary` in IE 10/11
|
||||||
|
* and Firefox.
|
||||||
|
* Correct `block` display not defined for `main` in IE 11.
|
||||||
|
*/
|
||||||
|
|
||||||
|
article,
|
||||||
|
aside,
|
||||||
|
details,
|
||||||
|
figcaption,
|
||||||
|
figure,
|
||||||
|
footer,
|
||||||
|
header,
|
||||||
|
hgroup,
|
||||||
|
main,
|
||||||
|
menu,
|
||||||
|
nav,
|
||||||
|
section,
|
||||||
|
summary {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct `inline-block` display not defined in IE 8/9.
|
||||||
|
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio,
|
||||||
|
canvas,
|
||||||
|
progress,
|
||||||
|
video {
|
||||||
|
display: inline-block; /* 1 */
|
||||||
|
vertical-align: baseline; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent modern browsers from displaying `audio` without controls.
|
||||||
|
* Remove excess height in iOS 5 devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio:not([controls]) {
|
||||||
|
display: none;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address `[hidden]` styling not present in IE 8/9/10.
|
||||||
|
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[hidden],
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the gray background color from active links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Improve readability when focused and also mouse hovered in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a:active,
|
||||||
|
a:hover {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text-level semantics
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: 1px dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address styling not present in Safari and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
dfn {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address variable `h1` font-size and margin within `section` and `article`
|
||||||
|
* contexts in Firefox 4+, Safari, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address styling not present in IE 8/9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mark {
|
||||||
|
background: #ff0;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address inconsistent and variable font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Embedded content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove border when inside `a` element in IE 8/9/10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct overflow not hidden in IE 9/10/11.
|
||||||
|
*/
|
||||||
|
|
||||||
|
svg:not(:root) {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grouping content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address margin not present in IE 8/9 and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 1em 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address differences between Firefox and other browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contain overflow in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address odd `em`-unit font size rendering in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
pre,
|
||||||
|
samp {
|
||||||
|
font-family: monospace, monospace;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Known limitation: by default, Chrome and Safari on OS X allow very limited
|
||||||
|
* styling of `select`, unless a `border` property is set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct color not being inherited.
|
||||||
|
* Known issue: affects color of disabled elements.
|
||||||
|
* 2. Correct font properties not being inherited.
|
||||||
|
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
color: inherit; /* 1 */
|
||||||
|
font: inherit; /* 2 */
|
||||||
|
margin: 0; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address `overflow` set to `hidden` in IE 8/9/10/11.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||||
|
* All other form control elements do not inherit `text-transform` values.
|
||||||
|
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
|
||||||
|
* Correct `select` style inheritance in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||||
|
* and `video` controls.
|
||||||
|
* 2. Correct inability to style clickable `input` types in iOS.
|
||||||
|
* 3. Improve usability and consistency of cursor style between image-type
|
||||||
|
* `input` and others.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
html input[type="button"], /* 1 */
|
||||||
|
input[type="reset"],
|
||||||
|
input[type="submit"] {
|
||||||
|
-webkit-appearance: button; /* 2 */
|
||||||
|
cursor: pointer; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-set default cursor for disabled elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button[disabled],
|
||||||
|
html input[disabled] {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove inner padding and border in Firefox 4+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
input::-moz-focus-inner {
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||||
|
* the UA stylesheet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
input {
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It's recommended that you don't attempt to style these elements.
|
||||||
|
* Firefox's implementation doesn't respect box-sizing, padding, or width.
|
||||||
|
*
|
||||||
|
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||||
|
* 2. Remove excess padding in IE 8/9/10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
|
||||||
|
* `font-size` values of the `input`, it causes the cursor style of the
|
||||||
|
* decrement button to change from `default` to `text`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
input[type="number"]::-webkit-inner-spin-button,
|
||||||
|
input[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
||||||
|
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
|
||||||
|
* (include `-moz` to future-proof).
|
||||||
|
*/
|
||||||
|
|
||||||
|
input[type="search"] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
-webkit-box-sizing: content-box; /* 2 */
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
|
||||||
|
* Safari (but not Chrome) clips the cancel button when the search input has
|
||||||
|
* padding (and `textfield` appearance).
|
||||||
|
*/
|
||||||
|
|
||||||
|
input[type="search"]::-webkit-search-cancel-button,
|
||||||
|
input[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define consistent border, margin, and padding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border: 1px solid #c0c0c0;
|
||||||
|
margin: 0 2px;
|
||||||
|
padding: 0.35em 0.625em 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct `color` not being inherited in IE 8/9/10/11.
|
||||||
|
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||||
|
*/
|
||||||
|
|
||||||
|
legend {
|
||||||
|
border: 0; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove default vertical scrollbar in IE 8/9/10/11.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't inherit the `font-weight` (applied by a rule above).
|
||||||
|
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
|
||||||
|
*/
|
||||||
|
|
||||||
|
optgroup {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove most spacing between table cells.
|
||||||
|
*/
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
padding: 0;
|
||||||
|
}
|
418
docker/fib/static/css/skeleton.css
vendored
Normal file
418
docker/fib/static/css/skeleton.css
vendored
Normal file
@@ -0,0 +1,418 @@
|
|||||||
|
/*
|
||||||
|
* Skeleton V2.0.4
|
||||||
|
* Copyright 2014, Dave Gamache
|
||||||
|
* www.getskeleton.com
|
||||||
|
* Free to use under the MIT license.
|
||||||
|
* http://www.opensource.org/licenses/mit-license.php
|
||||||
|
* 12/29/2014
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Table of contents
|
||||||
|
––––––––––––––––––––––––––––––––––––––––––––––––––
|
||||||
|
- Grid
|
||||||
|
- Base Styles
|
||||||
|
- Typography
|
||||||
|
- Links
|
||||||
|
- Buttons
|
||||||
|
- Forms
|
||||||
|
- Lists
|
||||||
|
- Code
|
||||||
|
- Tables
|
||||||
|
- Spacing
|
||||||
|
- Utilities
|
||||||
|
- Clearing
|
||||||
|
- Media Queries
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Grid
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
.container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 960px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
.column,
|
||||||
|
.columns {
|
||||||
|
width: 100%;
|
||||||
|
float: left;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
|
||||||
|
/* For devices larger than 400px */
|
||||||
|
@media (min-width: 400px) {
|
||||||
|
.container {
|
||||||
|
width: 85%;
|
||||||
|
padding: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For devices larger than 550px */
|
||||||
|
@media (min-width: 550px) {
|
||||||
|
.container {
|
||||||
|
width: 80%; }
|
||||||
|
.column,
|
||||||
|
.columns {
|
||||||
|
margin-left: 4%; }
|
||||||
|
.column:first-child,
|
||||||
|
.columns:first-child {
|
||||||
|
margin-left: 0; }
|
||||||
|
|
||||||
|
.one.column,
|
||||||
|
.one.columns { width: 4.66666666667%; }
|
||||||
|
.two.columns { width: 13.3333333333%; }
|
||||||
|
.three.columns { width: 22%; }
|
||||||
|
.four.columns { width: 30.6666666667%; }
|
||||||
|
.five.columns { width: 39.3333333333%; }
|
||||||
|
.six.columns { width: 48%; }
|
||||||
|
.seven.columns { width: 56.6666666667%; }
|
||||||
|
.eight.columns { width: 65.3333333333%; }
|
||||||
|
.nine.columns { width: 74.0%; }
|
||||||
|
.ten.columns { width: 82.6666666667%; }
|
||||||
|
.eleven.columns { width: 91.3333333333%; }
|
||||||
|
.twelve.columns { width: 100%; margin-left: 0; }
|
||||||
|
|
||||||
|
.one-third.column { width: 30.6666666667%; }
|
||||||
|
.two-thirds.column { width: 65.3333333333%; }
|
||||||
|
|
||||||
|
.one-half.column { width: 48%; }
|
||||||
|
|
||||||
|
/* Offsets */
|
||||||
|
.offset-by-one.column,
|
||||||
|
.offset-by-one.columns { margin-left: 8.66666666667%; }
|
||||||
|
.offset-by-two.column,
|
||||||
|
.offset-by-two.columns { margin-left: 17.3333333333%; }
|
||||||
|
.offset-by-three.column,
|
||||||
|
.offset-by-three.columns { margin-left: 26%; }
|
||||||
|
.offset-by-four.column,
|
||||||
|
.offset-by-four.columns { margin-left: 34.6666666667%; }
|
||||||
|
.offset-by-five.column,
|
||||||
|
.offset-by-five.columns { margin-left: 43.3333333333%; }
|
||||||
|
.offset-by-six.column,
|
||||||
|
.offset-by-six.columns { margin-left: 52%; }
|
||||||
|
.offset-by-seven.column,
|
||||||
|
.offset-by-seven.columns { margin-left: 60.6666666667%; }
|
||||||
|
.offset-by-eight.column,
|
||||||
|
.offset-by-eight.columns { margin-left: 69.3333333333%; }
|
||||||
|
.offset-by-nine.column,
|
||||||
|
.offset-by-nine.columns { margin-left: 78.0%; }
|
||||||
|
.offset-by-ten.column,
|
||||||
|
.offset-by-ten.columns { margin-left: 86.6666666667%; }
|
||||||
|
.offset-by-eleven.column,
|
||||||
|
.offset-by-eleven.columns { margin-left: 95.3333333333%; }
|
||||||
|
|
||||||
|
.offset-by-one-third.column,
|
||||||
|
.offset-by-one-third.columns { margin-left: 34.6666666667%; }
|
||||||
|
.offset-by-two-thirds.column,
|
||||||
|
.offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
|
||||||
|
|
||||||
|
.offset-by-one-half.column,
|
||||||
|
.offset-by-one-half.columns { margin-left: 52%; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Base Styles
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
/* NOTE
|
||||||
|
html is set to 62.5% so that all the REM measurements throughout Skeleton
|
||||||
|
are based on 10px sizing. So basically 1.5rem = 15px :) */
|
||||||
|
html {
|
||||||
|
font-size: 62.5%; }
|
||||||
|
body {
|
||||||
|
font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
|
||||||
|
line-height: 1.6;
|
||||||
|
font-weight: 400;
|
||||||
|
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
color: #222; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Typography
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
font-weight: 300; }
|
||||||
|
h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;}
|
||||||
|
h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }
|
||||||
|
h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; }
|
||||||
|
h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; }
|
||||||
|
h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; }
|
||||||
|
h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
|
||||||
|
|
||||||
|
/* Larger than phablet */
|
||||||
|
@media (min-width: 550px) {
|
||||||
|
h1 { font-size: 5.0rem; }
|
||||||
|
h2 { font-size: 4.2rem; }
|
||||||
|
h3 { font-size: 3.6rem; }
|
||||||
|
h4 { font-size: 3.0rem; }
|
||||||
|
h5 { font-size: 2.4rem; }
|
||||||
|
h6 { font-size: 1.5rem; }
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Links
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
a {
|
||||||
|
color: #1EAEDB; }
|
||||||
|
a:hover {
|
||||||
|
color: #0FA0CE; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Buttons
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
.button,
|
||||||
|
button,
|
||||||
|
input[type="submit"],
|
||||||
|
input[type="reset"],
|
||||||
|
input[type="button"] {
|
||||||
|
display: inline-block;
|
||||||
|
height: 38px;
|
||||||
|
padding: 0 30px;
|
||||||
|
color: #555;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 38px;
|
||||||
|
letter-spacing: .1rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
cursor: pointer;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
.button:hover,
|
||||||
|
button:hover,
|
||||||
|
input[type="submit"]:hover,
|
||||||
|
input[type="reset"]:hover,
|
||||||
|
input[type="button"]:hover,
|
||||||
|
.button:focus,
|
||||||
|
button:focus,
|
||||||
|
input[type="submit"]:focus,
|
||||||
|
input[type="reset"]:focus,
|
||||||
|
input[type="button"]:focus {
|
||||||
|
color: #333;
|
||||||
|
border-color: #888;
|
||||||
|
outline: 0; }
|
||||||
|
.button.button-primary,
|
||||||
|
button.button-primary,
|
||||||
|
input[type="submit"].button-primary,
|
||||||
|
input[type="reset"].button-primary,
|
||||||
|
input[type="button"].button-primary {
|
||||||
|
color: #FFF;
|
||||||
|
background-color: #33C3F0;
|
||||||
|
border-color: #33C3F0; }
|
||||||
|
.button.button-primary:hover,
|
||||||
|
button.button-primary:hover,
|
||||||
|
input[type="submit"].button-primary:hover,
|
||||||
|
input[type="reset"].button-primary:hover,
|
||||||
|
input[type="button"].button-primary:hover,
|
||||||
|
.button.button-primary:focus,
|
||||||
|
button.button-primary:focus,
|
||||||
|
input[type="submit"].button-primary:focus,
|
||||||
|
input[type="reset"].button-primary:focus,
|
||||||
|
input[type="button"].button-primary:focus {
|
||||||
|
color: #FFF;
|
||||||
|
background-color: #1EAEDB;
|
||||||
|
border-color: #1EAEDB; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Forms
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
input[type="email"],
|
||||||
|
input[type="number"],
|
||||||
|
input[type="search"],
|
||||||
|
input[type="text"],
|
||||||
|
input[type="tel"],
|
||||||
|
input[type="url"],
|
||||||
|
input[type="password"],
|
||||||
|
textarea,
|
||||||
|
select {
|
||||||
|
height: 38px;
|
||||||
|
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #D1D1D1;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: none;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
/* Removes awkward default styles on some inputs for iOS */
|
||||||
|
input[type="email"],
|
||||||
|
input[type="number"],
|
||||||
|
input[type="search"],
|
||||||
|
input[type="text"],
|
||||||
|
input[type="tel"],
|
||||||
|
input[type="url"],
|
||||||
|
input[type="password"],
|
||||||
|
textarea {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none; }
|
||||||
|
textarea {
|
||||||
|
min-height: 65px;
|
||||||
|
padding-top: 6px;
|
||||||
|
padding-bottom: 6px; }
|
||||||
|
input[type="email"]:focus,
|
||||||
|
input[type="number"]:focus,
|
||||||
|
input[type="search"]:focus,
|
||||||
|
input[type="text"]:focus,
|
||||||
|
input[type="tel"]:focus,
|
||||||
|
input[type="url"]:focus,
|
||||||
|
input[type="password"]:focus,
|
||||||
|
textarea:focus,
|
||||||
|
select:focus {
|
||||||
|
border: 1px solid #33C3F0;
|
||||||
|
outline: 0; }
|
||||||
|
label,
|
||||||
|
legend {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
font-weight: 600; }
|
||||||
|
fieldset {
|
||||||
|
padding: 0;
|
||||||
|
border-width: 0; }
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
display: inline; }
|
||||||
|
label > .label-body {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: .5rem;
|
||||||
|
font-weight: normal; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Lists
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
ul {
|
||||||
|
list-style: circle inside; }
|
||||||
|
ol {
|
||||||
|
list-style: decimal inside; }
|
||||||
|
ol, ul {
|
||||||
|
padding-left: 0;
|
||||||
|
margin-top: 0; }
|
||||||
|
ul ul,
|
||||||
|
ul ol,
|
||||||
|
ol ol,
|
||||||
|
ol ul {
|
||||||
|
margin: 1.5rem 0 1.5rem 3rem;
|
||||||
|
font-size: 90%; }
|
||||||
|
li {
|
||||||
|
margin-bottom: 1rem; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Code
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
code {
|
||||||
|
padding: .2rem .5rem;
|
||||||
|
margin: 0 .2rem;
|
||||||
|
font-size: 90%;
|
||||||
|
white-space: nowrap;
|
||||||
|
background: #F1F1F1;
|
||||||
|
border: 1px solid #E1E1E1;
|
||||||
|
border-radius: 4px; }
|
||||||
|
pre > code {
|
||||||
|
display: block;
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
white-space: pre; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Tables
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
padding: 12px 15px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #E1E1E1; }
|
||||||
|
th:first-child,
|
||||||
|
td:first-child {
|
||||||
|
padding-left: 0; }
|
||||||
|
th:last-child,
|
||||||
|
td:last-child {
|
||||||
|
padding-right: 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Spacing
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
button,
|
||||||
|
.button {
|
||||||
|
margin-bottom: 1rem; }
|
||||||
|
input,
|
||||||
|
textarea,
|
||||||
|
select,
|
||||||
|
fieldset {
|
||||||
|
margin-bottom: 1.5rem; }
|
||||||
|
pre,
|
||||||
|
blockquote,
|
||||||
|
dl,
|
||||||
|
figure,
|
||||||
|
table,
|
||||||
|
p,
|
||||||
|
ul,
|
||||||
|
ol,
|
||||||
|
form {
|
||||||
|
margin-bottom: 2.5rem; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Utilities
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
.u-full-width {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
.u-max-full-width {
|
||||||
|
max-width: 100%;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
.u-pull-right {
|
||||||
|
float: right; }
|
||||||
|
.u-pull-left {
|
||||||
|
float: left; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Misc
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
hr {
|
||||||
|
margin-top: 3rem;
|
||||||
|
margin-bottom: 3.5rem;
|
||||||
|
border-width: 0;
|
||||||
|
border-top: 1px solid #E1E1E1; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Clearing
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
|
||||||
|
/* Self Clearing Goodness */
|
||||||
|
.container:after,
|
||||||
|
.row:after,
|
||||||
|
.u-cf {
|
||||||
|
content: "";
|
||||||
|
display: table;
|
||||||
|
clear: both; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Media Queries
|
||||||
|
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||||
|
/*
|
||||||
|
Note: The best way to structure the use of media queries is to create the queries
|
||||||
|
near the relevant code. For example, if you wanted to change the styles for buttons
|
||||||
|
on small devices, paste the mobile query code up in the buttons section and style it
|
||||||
|
there.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Larger than mobile */
|
||||||
|
@media (min-width: 400px) {}
|
||||||
|
|
||||||
|
/* Larger than phablet (also point when grid becomes active) */
|
||||||
|
@media (min-width: 550px) {}
|
||||||
|
|
||||||
|
/* Larger than tablet */
|
||||||
|
@media (min-width: 750px) {}
|
||||||
|
|
||||||
|
/* Larger than desktop */
|
||||||
|
@media (min-width: 1000px) {}
|
||||||
|
|
||||||
|
/* Larger than Desktop HD */
|
||||||
|
@media (min-width: 1200px) {}
|
26
docker/fib/templates/index.html
Normal file
26
docker/fib/templates/index.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8' />
|
||||||
|
<link href='static/css/skeleton.css' rel='stylesheet' type='text/css' />
|
||||||
|
<title>Fibonacci Zahlen berechnen</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h2>Fibonacci Generator </h2
|
||||||
|
<!--FORM -->
|
||||||
|
<form action='fib' method='post'>
|
||||||
|
<label> Folgen Element</label>
|
||||||
|
<input
|
||||||
|
type='text'
|
||||||
|
placeholder='Fibonacci Element'
|
||||||
|
name='element'
|
||||||
|
value='{{request.form.element}}'
|
||||||
|
</input><br />
|
||||||
|
<button type='submit'>Berechnen</button>
|
||||||
|
<p>Formel: {{formel}} </p>
|
||||||
|
<p>Fibonacci-Zahl: {{result}} </p>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
8
docker/pyvenv.cfg
Normal file
8
docker/pyvenv.cfg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
home = /usr/bin
|
||||||
|
implementation = CPython
|
||||||
|
version_info = 3.11.2.final.0
|
||||||
|
virtualenv = 20.17.1+ds
|
||||||
|
include-system-site-packages = false
|
||||||
|
base-prefix = /usr
|
||||||
|
base-exec-prefix = /usr
|
||||||
|
base-executable = /usr/bin/python3
|
7
docker/requirements.txt
Normal file
7
docker/requirements.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
blinker==1.7.0
|
||||||
|
click==8.1.7
|
||||||
|
Flask==3.0.1
|
||||||
|
itsdangerous==2.1.2
|
||||||
|
Jinja2==3.1.3
|
||||||
|
MarkupSafe==2.1.3
|
||||||
|
Werkzeug==3.0.1
|
1
getattr/.gitignore
vendored
Normal file
1
getattr/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__pycache__
|
17
getattr/Kreis.py
Normal file
17
getattr/Kreis.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from math import pi as pi
|
||||||
|
|
||||||
|
|
||||||
|
class Kreis:
|
||||||
|
def __init__(self, radius):
|
||||||
|
self.radius = radius
|
||||||
|
|
||||||
|
def durchmesser(self):
|
||||||
|
return self.radius * 2
|
||||||
|
|
||||||
|
def umfang(self):
|
||||||
|
return self.durchmesser() * pi
|
||||||
|
|
||||||
|
def flaeche(self):
|
||||||
|
return self.radius** 2 * pi
|
||||||
|
|
||||||
|
|
19
getattr/Kreis_getattr.py
Normal file
19
getattr/Kreis_getattr.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from math import pi as pi
|
||||||
|
|
||||||
|
|
||||||
|
class Kreis_getattr:
|
||||||
|
def __init__(self, radius):
|
||||||
|
self.radius = radius
|
||||||
|
self.operators ={
|
||||||
|
'durchmesser': lambda x: self.radius * 2,
|
||||||
|
'umfang': lambda x: self.durchmesser * pi,
|
||||||
|
'flaeche': lambda x: self.radius**2 *pi
|
||||||
|
}
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if name not in self.operators:
|
||||||
|
raise TypeError(f'unbekannte Operation {name}')
|
||||||
|
|
||||||
|
return self.operators[name](0)
|
||||||
|
|
||||||
|
|
17
getattr/name.py
Normal file
17
getattr/name.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
class Name:
|
||||||
|
def __init__(self,vorname,name):
|
||||||
|
self.vorname = vorname
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __getattr__(self,attr):
|
||||||
|
if attr == 'fullname':
|
||||||
|
return self.vorname + ' ' + self.name
|
||||||
|
elif attr == 'sortname':
|
||||||
|
return self.name + ',' + self.vorname
|
||||||
|
else:
|
||||||
|
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{attr}'")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
36
getattr/testKreis.py
Normal file
36
getattr/testKreis.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import unittest
|
||||||
|
import Kreis
|
||||||
|
import Kreis_getattr
|
||||||
|
|
||||||
|
|
||||||
|
class TestKreis(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.kreis = Kreis.Kreis(1)
|
||||||
|
self.kreis_getattr = Kreis_getattr.Kreis_getattr(1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_Umfang(self):
|
||||||
|
umfang = self.kreis.umfang()
|
||||||
|
umfang_getattr = self.kreis_getattr.umfang
|
||||||
|
print(f'kreis Umfang {umfang}')
|
||||||
|
print(f'kreis_gettattr Umfang {umfang_getattr}')
|
||||||
|
self.assertEqual(umfang, umfang_getattr)
|
||||||
|
|
||||||
|
def test_Flaeche(self):
|
||||||
|
flaeche = self.kreis.flaeche()
|
||||||
|
flaeche_getattr = self.kreis_getattr.flaeche
|
||||||
|
print(f'kreis Fläche {flaeche}')
|
||||||
|
print(f'kreis_gettattr Fläche {flaeche_getattr}')
|
||||||
|
self.assertEqual(flaeche, flaeche_getattr)
|
||||||
|
|
||||||
|
def test_Durchmesser(self):
|
||||||
|
durchmesser = self.kreis.durchmesser()
|
||||||
|
durchmesser_getattr = self.kreis_getattr.durchmesser
|
||||||
|
print(f'kreis Durchmesser {durchmesser}')
|
||||||
|
print(f'kreis_gettattr Durchmesser {durchmesser_getattr}')
|
||||||
|
self.assertEqual(durchmesser, durchmesser_getattr)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
28
getattr/testname.py
Normal file
28
getattr/testname.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import unittest
|
||||||
|
import logging
|
||||||
|
from name import Name
|
||||||
|
|
||||||
|
__LOGLEVEL__ = logging.DEBUG
|
||||||
|
|
||||||
|
logging.basicConfig( format='%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s', level=__LOGLEVEL__)
|
||||||
|
|
||||||
|
class TestName(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
logging.debug('setting up test')
|
||||||
|
self.name = Name('Homer', 'Simpson')
|
||||||
|
|
||||||
|
def test_getattr(self):
|
||||||
|
fullname = self.name.fullname
|
||||||
|
sortname = self.name.sortname
|
||||||
|
|
||||||
|
|
||||||
|
self.assertEqual('Homer Simpson', fullname)
|
||||||
|
self.assertEqual('Simpson,Homer', sortname)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
logging.debug('Test startet.')
|
||||||
|
unittest.main()
|
||||||
|
|
||||||
|
|
3
rest_chat_server/.gitignore
vendored
Normal file
3
rest_chat_server/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
__pycache__
|
||||||
|
.venv
|
||||||
|
*.log
|
1
rest_chat_server/.python-version
Normal file
1
rest_chat_server/.python-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.9
|
0
rest_chat_server/README.md
Normal file
0
rest_chat_server/README.md
Normal file
83
rest_chat_server/chat_server.py
Normal file
83
rest_chat_server/chat_server.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import falcon, json
|
||||||
|
import logging
|
||||||
|
from logging import config
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class Message:
|
||||||
|
|
||||||
|
def __init__(self,user, text):
|
||||||
|
|
||||||
|
self.user = user
|
||||||
|
self.text = text
|
||||||
|
self.created = datetime.now()
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.text
|
||||||
|
|
||||||
|
class ChatServer(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.msglist = {}
|
||||||
|
|
||||||
|
initmsg = Message('system','Chat Server bereit')
|
||||||
|
|
||||||
|
self.addMsg(initmsg)
|
||||||
|
|
||||||
|
def addMsg(self,msg):
|
||||||
|
created = datetime.now()
|
||||||
|
self.msglist[created.strftime('%d.%m.%y %H:%M.%f')] = msg
|
||||||
|
|
||||||
|
def on_get(self,req,resp):
|
||||||
|
logging.debug('on_get()')
|
||||||
|
|
||||||
|
logging.debug(f'msglist= {self.msglist}')
|
||||||
|
json_msgs = {}
|
||||||
|
|
||||||
|
for key in self.msglist:
|
||||||
|
text = self.msglist[key].text
|
||||||
|
json_msgs[key] = {
|
||||||
|
'key': key,
|
||||||
|
'user': self.msglist[key].user,
|
||||||
|
'text': text
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.status = falcon.HTTP_OK
|
||||||
|
resp.media = json_msgs
|
||||||
|
|
||||||
|
def on_post(self,req,resp):
|
||||||
|
logging.debug('on_post()')
|
||||||
|
|
||||||
|
json_string = req.media
|
||||||
|
|
||||||
|
logging.debug(f'json_string={json_string}')
|
||||||
|
|
||||||
|
msg = Message(json_string['user'],json_string['text'])
|
||||||
|
self.addMsg(msg)
|
||||||
|
|
||||||
|
|
||||||
|
resp.status = falcon.HTTP_OK
|
||||||
|
|
||||||
|
def on_delete(self,req,resp):
|
||||||
|
logging.debug('on_delete()')
|
||||||
|
|
||||||
|
|
||||||
|
def create_chat_resource():
|
||||||
|
chat_endpoint = ChatServer()
|
||||||
|
|
||||||
|
logging.debug(f'endpoint={chat_endpoint}')
|
||||||
|
|
||||||
|
return chat_endpoint
|
||||||
|
|
||||||
|
|
||||||
|
application = falcon.App()
|
||||||
|
|
||||||
|
with open('log_config.json') as file_config:
|
||||||
|
config.dictConfig(json.load(file_config))
|
||||||
|
|
||||||
|
resource = create_chat_resource()
|
||||||
|
application.add_route('/msg', resource)
|
||||||
|
logging.debug('Chat REST Service bereit')
|
||||||
|
|
||||||
|
|
6
rest_chat_server/hello.py
Normal file
6
rest_chat_server/hello.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
def main():
|
||||||
|
print("Hello from rest-chat-server!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
28
rest_chat_server/log_config.json
Normal file
28
rest_chat_server/log_config.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"version":1,
|
||||||
|
"formatters":{
|
||||||
|
"std_out":{
|
||||||
|
"format": "%(asctime)s : %(levelname)s : %(module)s : %(funcName)s : %(lineno)d : (Process Details : (%(process)d, %(processName)s), Thread Details : (%(thread)d, %(threadName)s))\nLog : %(message)s",
|
||||||
|
"datefmt":"%d-%m-%Y %I:%M:%S"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"handlers":{
|
||||||
|
"console":{
|
||||||
|
"formatter": "std_out",
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"level": "DEBUG"
|
||||||
|
},
|
||||||
|
"file":{
|
||||||
|
"formatter":"std_out",
|
||||||
|
"class":"logging.FileHandler",
|
||||||
|
"level":"DEBUG",
|
||||||
|
"filename" : "chat_server.log"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root":{
|
||||||
|
"handlers":["console","file"],
|
||||||
|
"level": "DEBUG"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
10
rest_chat_server/pyproject.toml
Normal file
10
rest_chat_server/pyproject.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[project]
|
||||||
|
name = "rest-chat-server"
|
||||||
|
version = "0.0.1"
|
||||||
|
description = "Chat Server mit REST"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
dependencies = [
|
||||||
|
"falcon>=4.0.2",
|
||||||
|
"gunicorn>=23.0.0",
|
||||||
|
]
|
87
rest_chat_server/uv.lock
generated
Normal file
87
rest_chat_server/uv.lock
generated
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
version = 1
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "falcon"
|
||||||
|
version = "4.0.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/37/4f/d317952294dee1982cd930c8ee2b8b7fbf04140473882801061b3346c713/falcon-4.0.2.tar.gz", hash = "sha256:58f4b9c9da4c9b1e2c9f396ad7ef897701b3c7c7c87227f0bd1aee40c7fbc525", size = 630121 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b0/75/e33013aedec976d13f2104ab2e054b5e3863b518c9b28239d2837b521d7f/falcon-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8eab0212e77017385d48be2dfe9f5b32305fc9e4066cd298e4bb39e666e114c8", size = 2315204 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/90/5f/4a3ccb6d8bdb4cfcc38aea9cd5e5c49aea400305f581c839be206c3a93e2/falcon-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:942129dd3bfb56342ac368f05ff4f9be53e98883b4227089fce2fd616ebc6ef3", size = 2194755 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/28/99/447d6f8618b3f8b882c7e74eafabb59f6e9112acbc3255dddd353fc75505/falcon-4.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60e7b6e5ee44bb2411a7f47bb64e0b225f11cca6ddf91e5130d456242095f0d7", size = 10390701 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/27/a93dc68be1e70809cfa6d227424790ff502cc1f4272200bb91ebe92fafb1/falcon-4.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:330f1623e579575a9e3d90c2a15aebe100b2afa1e18a4bee2ddaa9a570e97902", size = 10986193 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/22/aae29170b0947a5170844bf74b671b5e0e6dc218e2cc6262d2378ec44d15/falcon-4.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d7cfac5cfca69373d1f65211d75767ed4f2d53b46554307427ec00a6f7f87c1", size = 10511133 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2f/73/0862e66b5b9c5295f065ee7c83571fd106dd84d63cf0479038986ddf2881/falcon-4.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:da3d942dd34f7a5213987bd053c3b52b6eb75fcfd342dc4fea9241f79a6529b3", size = 10201951 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/4f/044454ad96a542f2c446a07b6ebc8da0bef8e7e689e32aeb2bf40594a712/falcon-4.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5169e064bbe5dece52e088e3e8b17cae429f1e04c7aef8c31ae350303b19c620", size = 10633849 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2f/73/bd689c2790c42b6287df1a43928ae3af6cd2541ac1d64d6fa2fc960dad5b/falcon-4.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:0d62e565b9e71b52b59e03130b2b71345a6873f5299aad6a141caf4a58661b41", size = 2115914 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/e3/dfeff966d60f2308f765736044e0a62f046d2420baf50fa4872b06338fd5/falcon-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cb6ee1aee9ff6a656762cf5fcd2e6c5dced410ca990016be2bc193e6b74ae9da", size = 2321291 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/73/02/8a1a68ddf9b6f9d4a7d0d63f0a485109318f08c0181a3d9f4b05dceab355/falcon-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f1a16d8bdc8ef9cf2832a6ca6d43b156b613fb1587cd08cc928c7b8a118ea0a", size = 2196225 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/64/6fa45987bd0fc78d991be5ea0e30f0812eb26713c2e99ce07e35c959346b/falcon-4.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aee81fc4702eef5bccb640b93187fdf36ca2606fca511982069dbc60be2d1c93", size = 11603829 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/84/ef/bc1d47ee32e2a211cffca346bd935009d2b37189c2119df95c31a9af6231/falcon-4.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c1dbcec63d9118c3dfac1f810305128c4fffe26f4f99a7b4e379dec95fc3bfc", size = 12146705 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e9/cd/ef07fd256c2a29d3c3f1cc22e0ce59724450eb13ef5ca553e63b6abd19f7/falcon-4.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2892ab1232d3a7cc9890b1b539c471fe04c54f826704f9d05efe5632f18efa1", size = 11693278 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/2b/e03066e7be01f1b09c87ecd9c48e14a0ddafd9fc8fddd05db27b5ad4e3d9/falcon-4.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:af68482b408bde53a77b36e45317767dfc5b6fce1525f5b25d65f57f35d33fca", size = 11379786 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2d/15/f218b581df1447f743b16812c84ab8f6f7d51fb3c1950129744f6fd653bc/falcon-4.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:53d84de83abe1a2094b319a4f018ab6c5773d9c2c841b528662aa151ab9df35c", size = 11770361 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/11/3e/855c3051cb8aad61a921959e5e62416d759761241c1da8394103c3d1d6af/falcon-4.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:1d06bbbccdb58522b2a6bb2e79074844b0db0da1fff407725858a02515e15bbd", size = 2124712 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/67/db/0b78b7ee3fe7e370ed430b7deabfa524b57a5b9eb32622ce1f1bb7aacf0d/falcon-4.0.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:23b0419a9a025745734022aaa2e65447595e539ba27352b3f59d86b288f614db", size = 2294078 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/63/01/77b5b0214bc4ca717b6c6cbe8c3adaba653a7312c9c51a9b390f66efbce0/falcon-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:524d7b75f7368fe82e94ed16370db5a27bb4b2d066470cba53f02304264447e8", size = 2186007 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1d/0c/44abd34e38b88f15c5a7030f48ec079669218af3162de2bd1925e13a46a5/falcon-4.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c6b1d7451d5dee4be9b67a75e2a4a0b024dccffedd4e7c7a09513733b5a11db", size = 11644341 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5e/f3/0260f70dd080d23372e2ff0e330ca37897ab5e1b4890df281558bda8e34a/falcon-4.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59bb4a29626c5e610c62620a1395755e8c7b5509385b80d3637fbc8a604d29a3", size = 12218712 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8d/f8/704b73fc76cf283504aaacc2f466a08fd5d440cddd8d50b6d5c288f0293b/falcon-4.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26c9ed2912ee48e2e1e7eca3e7e85ab664ff07bd321097a26e4ad6168059424", size = 11842131 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f2/9a/53f9ee7ee8758972d92bb3dfb2225a9c382fbd12f684616cab9126420602/falcon-4.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0a12bbf3482b7ef1db0c6727c2ad8be5c3ac777d892e56a170e0b4b93651c915", size = 11346087 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/ac/8098957dd5b97ed16788104b7acb33c64689f7ab04e0c6b07d6561182950/falcon-4.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a601de7816138f17bf168262e0bceb128fdd1ea2f29ddae035585b5da9223a21", size = 11992383 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/23/f8a74294b5b0cb5b9e3eb44ccea310a5d480ef95e938704827db0dd97f99/falcon-4.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:eec3feda4a9cd773203401e3cf425728a13bf5055b22243b1452e9ad963634f5", size = 2077409 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1f/34/71ef64406ac7f83c5726a37c9fcae0578bc9d650de09c32148aa6c58502f/falcon-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:110b172afe337fbae802f1402c89a5dfe6392f3b8ce4f2ecdfd5cee48f68b805", size = 2257265 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/13/528d074e8a75a9236c9f060685e4cb813fbca774269afc89d31e821d8560/falcon-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b3a5db14cf2ef05f8f9630468c03939b86dc16115a5250a1870dac3dca1e04ba", size = 2151133 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2f/70/8c7bf8bf941238a87debce72fcdc7b2301d6599271a392c8216ea2f5d91e/falcon-4.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e0b4d41ce29c2b5c5b18021320e9e0977ba47ade46b67face52ee1325e2ea4", size = 11438997 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fa/43/71e358d36ec4559737d63312d746fb5f8b0e64f1fe273cd6991e567a9225/falcon-4.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:56af3b8838da2e19ae56b4e1bac168669ba257d6941f94933dc4f814fe721c08", size = 12015197 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/70/c10acaa3486748f77d9b0e79aaa19d3023b760bb9b93389ac1883a52e366/falcon-4.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec939d26dd77f57f08f3e13fb14b4e609c0baf073dc3f0c368f0e4cc10439528", size = 11653687 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/3b/dfdd9bd9f6114a49a55298b12048f1b65d0813b82c28676b956c4444f707/falcon-4.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9bfd751dd898505e17152d7ecfcdc457c9d85bceed7e651a9915183bd4afc86b", size = 11165291 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/61/eb3d1d2076df85d5a7c2cd823ba5dbe0a928053a3102effb9006b2851377/falcon-4.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b85f9c6f50a7465303290cb305404ea5c1ddeff6702179c1a8879c4693b0e5e", size = 11831049 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/c7/268cddb1f84ebe5b402acdf116083658f3fb0dd38a75571e0ee703cef212/falcon-4.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:a410e4023999a74ccf615fafa646b112044b987ef5901c8e5c5b79b163f2b3ba", size = 2052994 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d0/00/7be6347247812e6553be50d83b0951e569d597b9c3a71e4c0de5b00789b7/falcon-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f9709fd9181f58d492463b951cc42fb33b230e8f261128bc8252a37a4553f318", size = 2323679 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c4/71/65266fc8433e396f42a2b045e7b7069390c4314e8b66e66c4e092166226f/falcon-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:427c20ceb367039b856506d7baeef17c7f0c40b8fcbf1147c0e76f33a574a7cf", size = 2203699 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/80/30/82ff9d61d6baa5f908ccbbb775585cd1ac24dd47fcc2d2e6c5b9b0f44ce4/falcon-4.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fb50cebc3cae6720ccf4a05fccb233ea6a88e803828a07c063d6dce10a74e0e", size = 10418688 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/e5/660262ee87a90aab812d2d10ab42e6e0bffe853890b2e14268863c4dd659/falcon-4.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:628c450e14af811f13db6334265d7ff8a7b8a25ece1bde35d09a367a72046533", size = 11033845 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8f/b2/cf4c9567ad571e3304743e6f65c42576929cc16d494cb234f972fa70a150/falcon-4.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e04b30a7f89e5413e00c5cd1ea62bf7948323eb0220f8a5bbf705abae266a384", size = 10547880 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e2/b8/503d3574be76a09b64dd48214e012fd1b911a158400bc04b1ee0d4caec0f/falcon-4.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9095a36b8eeb80207322393b3bc88edaacd0426c2907e8427617618421bde9cc", size = 10218888 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2c/88/d96a3e9d93aee74280a82be844c2eaa603283c5548b3293165deb2d55b4e/falcon-4.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0adc6c2887f9d7ed55fe38edef055cc85c26762e392d80dca8765184c180b921", size = 10663138 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/38/97/4021fce87e3feb67839405ca8d2560d989da141692214c6f1b297af23443/falcon-4.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:7bffb4cadcbf7c5994695d421ef5305ad8315cfbefe971713046967614f0ffa4", size = 2121203 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/20/e2/ef821224a9ca9d4bb81d6e7ba60c6fbf3eae2e0dc10d806e6ff21b6dfdc5/falcon-4.0.2-py3-none-any.whl", hash = "sha256:077b2abf001940c6128c9b5872ae8147fe13f6ca333f928d8045d7601a5e847e", size = 318356 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gunicorn"
|
||||||
|
version = "23.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "packaging" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/34/72/9614c465dc206155d93eff0ca20d42e1e35afc533971379482de953521a4/gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec", size = 375031 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/7d/6dac2a6e1eba33ee43f318edbed4ff29151a49b5d37f080aad1e6469bca4/gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d", size = 85029 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "packaging"
|
||||||
|
version = "25.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rest-chat-server"
|
||||||
|
version = "0.0.1"
|
||||||
|
source = { virtual = "." }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "falcon" },
|
||||||
|
{ name = "gunicorn" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [
|
||||||
|
{ name = "falcon", specifier = ">=4.0.2" },
|
||||||
|
{ name = "gunicorn", specifier = ">=23.0.0" },
|
||||||
|
]
|
2
teil13/.gitignore
vendored
2
teil13/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
./__pycache__
|
__pycache__
|
||||||
./network/__pycache__/*
|
./network/__pycache__/*
|
||||||
|
2
teil16/.gitignore
vendored
2
teil16/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
./__pycache__
|
__pycache__
|
||||||
./network/__pycache__/*
|
./network/__pycache__/*
|
||||||
|
47
teil16/plztest.py
Normal file
47
teil16/plztest.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
import unittest
|
||||||
|
import logging
|
||||||
|
import re #regular expressions
|
||||||
|
|
||||||
|
logging.basicConfig( format='%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s', level=logging.DEBUG)
|
||||||
|
|
||||||
|
class TestPLZ(unittest.TestCase):
|
||||||
|
|
||||||
|
# Korrektes Format der PLZ prüfen. Falsche Version
|
||||||
|
|
||||||
|
def checkPLZ_falsch(self,plz):
|
||||||
|
try:
|
||||||
|
if len(pl) == 5 and int(plz) > 0:
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def checkPLZ_korrekt(self,plz):
|
||||||
|
#regulären Audruck aufbauen, genau 5 Ziffern.
|
||||||
|
pattern = re.compile('\d\d\d\d\d')
|
||||||
|
#Ausdruck auf String anwenden.
|
||||||
|
return pattern.match(plz)
|
||||||
|
|
||||||
|
|
||||||
|
# Die setUp() Methode wird zu Beginn jedes Testcases aufgrufen
|
||||||
|
def setUp(self):
|
||||||
|
logging.debug('setting up test')
|
||||||
|
self.testdaten = ['42287','42289','42119','42277','44139','-1111']
|
||||||
|
|
||||||
|
def test_false_positive(self):
|
||||||
|
|
||||||
|
for plz in self.testdaten:
|
||||||
|
self.assertTrue(self.checkPLZ_falsch(plz))
|
||||||
|
|
||||||
|
def test_plz(self):
|
||||||
|
|
||||||
|
logging.debug('starte test_plz()')
|
||||||
|
for plz in self.testdaten:
|
||||||
|
logging.debug(f'teste ${plz}')
|
||||||
|
self.assertTrue(self.checkPLZ_korrekt(plz))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
@@ -11,5 +11,5 @@ def fib_generator():
|
|||||||
fibo = fib_generator()
|
fibo = fib_generator()
|
||||||
|
|
||||||
|
|
||||||
for _ in range(int(sys.argv[1])+1):
|
for _ in range(int(sys.argv[1])):
|
||||||
print(next(fibo))
|
print(next(fibo))
|
||||||
|
6
teil24/.gitignore
vendored
Normal file
6
teil24/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# created by virtualenv automatically
|
||||||
|
__pycache__
|
||||||
|
bin
|
||||||
|
lib
|
||||||
|
share
|
||||||
|
*.csv
|
19
teil24/match_list.py
Normal file
19
teil24/match_list.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
def print_match(wert):
|
||||||
|
|
||||||
|
print(f'wert={wert}')
|
||||||
|
match wert:
|
||||||
|
case 1|2:
|
||||||
|
print('1 oder 2')
|
||||||
|
case 3|4:
|
||||||
|
print('3 oder 4')
|
||||||
|
case _:
|
||||||
|
print('unbekannt')
|
||||||
|
|
||||||
|
|
||||||
|
print_match(1)
|
||||||
|
print_match(3)
|
||||||
|
print_match(5)
|
||||||
|
|
||||||
|
|
||||||
|
|
11
teil24/match_structure.py
Normal file
11
teil24/match_structure.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
values= ['John']
|
||||||
|
# Matching structure in Python switch-case
|
||||||
|
match values:
|
||||||
|
case [a]:
|
||||||
|
print(f'Only one item: {a}')
|
||||||
|
case [a, b]:
|
||||||
|
print(f'Two items: {a}, {b}')
|
||||||
|
case [a, b, c]:
|
||||||
|
print(f'Three items: {a}, {b}, and {c}')
|
||||||
|
case [a, b, c, *rest]:
|
||||||
|
print(f'More than three items: {a}, {b}, {c}, as well as: {rest}')
|
19
teil24/print_class.py
Normal file
19
teil24/print_class.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
def print_match(name):
|
||||||
|
|
||||||
|
print(f'name={name}')
|
||||||
|
match name:
|
||||||
|
case 'Lisa'|'Ralph'|'Janey':
|
||||||
|
print('zweite Klasse bei Ms. Hoover')
|
||||||
|
case 'Bart'|'Milhouse'|'Nelson':
|
||||||
|
print('vierte Klasse bei Ms. Krabappel')
|
||||||
|
case _:
|
||||||
|
print('unbekannt')
|
||||||
|
|
||||||
|
|
||||||
|
print_match('Lisa')
|
||||||
|
print_match('Milhouse')
|
||||||
|
print_match('Homer')
|
||||||
|
|
||||||
|
|
||||||
|
|
23
teil24/print_tag_elif.py
Normal file
23
teil24/print_tag_elif.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
num=5
|
||||||
|
|
||||||
|
def print_wochentag(num):
|
||||||
|
if num == 0:
|
||||||
|
print('Montag')
|
||||||
|
elif num == 1:
|
||||||
|
print('Dienstag')
|
||||||
|
elif num == 2:
|
||||||
|
print('Mittwoch')
|
||||||
|
elif num == 3:
|
||||||
|
print('Donnerstag')
|
||||||
|
elif num == 4:
|
||||||
|
print('Freitag')
|
||||||
|
elif num == 5:
|
||||||
|
print('Samstag')
|
||||||
|
elif num == 6:
|
||||||
|
print('Sonntag')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print_wochentag(int(sys.argv[1]))
|
||||||
|
|
28
teil24/print_tag_match.py
Normal file
28
teil24/print_tag_match.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
num=5
|
||||||
|
|
||||||
|
def print_wochentag(num):
|
||||||
|
|
||||||
|
match num:
|
||||||
|
case 0:
|
||||||
|
print('Montag')
|
||||||
|
case 1:
|
||||||
|
print('Dienstag')
|
||||||
|
case 2:
|
||||||
|
print('Mittwoch')
|
||||||
|
case 3:
|
||||||
|
print('Donnerstag')
|
||||||
|
case 4:
|
||||||
|
print('Freitag')
|
||||||
|
case 5:
|
||||||
|
print('Samstag')
|
||||||
|
case 6:
|
||||||
|
print('Sonntag')
|
||||||
|
case _:
|
||||||
|
print('unbekannte Eingabe')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print_wochentag(int(sys.argv[1]))
|
||||||
|
|
28
teil24/print_tag_match_str.py
Normal file
28
teil24/print_tag_match_str.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
num=5
|
||||||
|
|
||||||
|
def print_wochentag(num):
|
||||||
|
|
||||||
|
match num:
|
||||||
|
case '0':
|
||||||
|
print('Montag')
|
||||||
|
case '1':
|
||||||
|
print('Dienstag')
|
||||||
|
case '2':
|
||||||
|
print('Mittwoch')
|
||||||
|
case '3':
|
||||||
|
print('Donnerstag')
|
||||||
|
case '4':
|
||||||
|
print('Freitag')
|
||||||
|
case '5':
|
||||||
|
print('Samstag')
|
||||||
|
case '6':
|
||||||
|
print('Sonntag')
|
||||||
|
case _:
|
||||||
|
print('unbekannte Eingabe')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print_wochentag(sys.argv[1])
|
||||||
|
|
23
teil24/print_type.py
Normal file
23
teil24/print_type.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#encoding:utf-8
|
||||||
|
def print_type(value):
|
||||||
|
match value:
|
||||||
|
case int():
|
||||||
|
print('Integer')
|
||||||
|
case str():
|
||||||
|
print('String')
|
||||||
|
case list():
|
||||||
|
print('Liste')
|
||||||
|
case dict() as d:
|
||||||
|
print(f'Dictionary mit {len(d)} Einträgen')
|
||||||
|
case _:
|
||||||
|
print('unbekannter Datentyp')
|
||||||
|
|
||||||
|
print_type(1) #Integer
|
||||||
|
|
||||||
|
print_type('The Simpsons') # String
|
||||||
|
|
||||||
|
print_type([1, 2, 3]) # Liste
|
||||||
|
|
||||||
|
print_type({'a': 1, 'b': 2, 'c': 3}) # Dictionary
|
||||||
|
|
||||||
|
print_type(1.0) #float ist nicht implentiert
|
8
teil24/pyvenv.cfg
Normal file
8
teil24/pyvenv.cfg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
home = /usr/bin
|
||||||
|
implementation = CPython
|
||||||
|
version_info = 3.11.2.final.0
|
||||||
|
virtualenv = 20.17.1+ds
|
||||||
|
include-system-site-packages = false
|
||||||
|
base-prefix = /usr
|
||||||
|
base-exec-prefix = /usr
|
||||||
|
base-executable = /usr/bin/python3
|
6
teil25/.gitignore
vendored
Normal file
6
teil25/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# created by virtualenv automatically
|
||||||
|
bin/
|
||||||
|
lib/
|
||||||
|
__pycache__
|
||||||
|
pyenv.cfg
|
||||||
|
*.bak
|
2560
teil25/Vornamen_Wuppertal_2020.csv
Normal file
2560
teil25/Vornamen_Wuppertal_2020.csv
Normal file
File diff suppressed because it is too large
Load Diff
21
teil25/filter_vornamen.py
Normal file
21
teil25/filter_vornamen.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from vornamen_reader import read_vornamen
|
||||||
|
import re
|
||||||
|
|
||||||
|
def print_vornamen_simple(vornamen):
|
||||||
|
for vorname in vornamen:
|
||||||
|
print(vorname)
|
||||||
|
|
||||||
|
def print_vornamen_filtered(vornamen,regex):
|
||||||
|
pattern = re.compile(regex)
|
||||||
|
for vorname in vornamen:
|
||||||
|
# print(f"{type(r)}: {r}")
|
||||||
|
# s = re.findall(regex,vorname)
|
||||||
|
# if s[0] != '':
|
||||||
|
is_match = pattern.match(vorname).span()[1] >0
|
||||||
|
if is_match:
|
||||||
|
print(f'{is_match}: {vorname}')
|
||||||
|
|
||||||
|
vornamen = read_vornamen('./Vornamen_Wuppertal_2020.csv')
|
||||||
|
|
||||||
|
#print_vornamen_simple(vornamen)
|
||||||
|
print_vornamen_filtered(vornamen,'O*')
|
22
teil25/phone.py
Normal file
22
teil25/phone.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import re
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class RegEx(unittest.TestCase):
|
||||||
|
|
||||||
|
pattern_phone = re.compile(r'\D')
|
||||||
|
pattern_digits_only = re.compile(r'\d')
|
||||||
|
|
||||||
|
def test_phone(self):
|
||||||
|
|
||||||
|
m = self.pattern_phone.sub('','+1 (212) 555-6832')
|
||||||
|
|
||||||
|
self.assertIsNotNone(self.pattern_digits_only.match(m))
|
||||||
|
|
||||||
|
print(f'm={m}')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
8
teil25/pyvenv.cfg
Normal file
8
teil25/pyvenv.cfg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
home = /usr/bin
|
||||||
|
implementation = CPython
|
||||||
|
version_info = 3.11.2.final.0
|
||||||
|
virtualenv = 20.17.1+ds
|
||||||
|
include-system-site-packages = false
|
||||||
|
base-prefix = /usr
|
||||||
|
base-exec-prefix = /usr
|
||||||
|
base-executable = /usr/bin/python3
|
101
teil25/regex.py
Normal file
101
teil25/regex.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import re
|
||||||
|
import unittest
|
||||||
|
import logging
|
||||||
|
|
||||||
|
pattern_char_only = re.compile('^[A-Z][a-z]+$')
|
||||||
|
pattern_digits_only = re.compile(r'\d+')
|
||||||
|
pattern_no_digits = re.compile(r'\D+')
|
||||||
|
pattern_plz = re.compile('^[0-9]{5}$')
|
||||||
|
pattern_plz2 = re.compile('^\d{5}$')
|
||||||
|
pattern_quote= re.compile(':')
|
||||||
|
pattern_tab = re.compile(r'\t')
|
||||||
|
pattern_simpson = re.compile('Simpson')
|
||||||
|
pattern_simple = re.compile('O*')
|
||||||
|
|
||||||
|
logging.basicConfig( format='%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s', level=logging.DEBUG)
|
||||||
|
|
||||||
|
# Unittest für die Demonstration von regular expressions (re)
|
||||||
|
class TestRegEgEx(unittest.TestCase):
|
||||||
|
|
||||||
|
# match: Passt der String auf die re
|
||||||
|
def test_match(self):
|
||||||
|
m = pattern_char_only.match('Olli')
|
||||||
|
|
||||||
|
logging.debug(f'm={m}')
|
||||||
|
self.assertTrue(m.span()[1] >0)
|
||||||
|
|
||||||
|
# Sucht alle Vorkommnisse der re im String
|
||||||
|
def test_findall(self):
|
||||||
|
s = '5 Äpfel, 10 Bananen, 42 Erdbeeren'
|
||||||
|
logging.debug(f' nur Ziffern: {pattern_digits_only.findall(s)}')
|
||||||
|
logging.debug(f' keine Ziffern: {pattern_no_digits.findall(s)}')
|
||||||
|
m = pattern_char_only.findall('Olli')
|
||||||
|
logging.debug(f'm={m}')
|
||||||
|
self.assertIsNotNone(m)
|
||||||
|
|
||||||
|
# Prüft die Gültigkeit einer Postleitzahl ('^\d{5}$' genau 5 Ziffern)
|
||||||
|
def test_plz(self):
|
||||||
|
patterns = [pattern_plz,pattern_plz2]
|
||||||
|
plz = ['42275','5600']
|
||||||
|
|
||||||
|
for pattern in patterns:
|
||||||
|
m = pattern.findall(plz[0])
|
||||||
|
logging.debug(f'm={m}')
|
||||||
|
self.assertNotEqual('',m[0])
|
||||||
|
m = pattern.findall(plz[1])
|
||||||
|
logging.debug(f'm={m}')
|
||||||
|
self.assertEqual([],m)
|
||||||
|
|
||||||
|
|
||||||
|
# Test für Suche
|
||||||
|
def test_search(self):
|
||||||
|
m = pattern_char_only.search('Olli')
|
||||||
|
logging.debug(f'm={m}')
|
||||||
|
#String passt auf die regular expression
|
||||||
|
self.assertIsNotNone(m)
|
||||||
|
|
||||||
|
m = pattern_char_only.search('123456')
|
||||||
|
logging.debug(f'm={m}')
|
||||||
|
#Dieser String passt nicht.
|
||||||
|
self.assertIsNone(m)
|
||||||
|
|
||||||
|
# Test zum Splitting (der Satz wird am ':' in die Worte zerlegt)
|
||||||
|
def test_split(self):
|
||||||
|
m = pattern_quote.split(' Die:Würde:des:Menschen:ist:unantastbar.')
|
||||||
|
logging.debug(f'm={m}')
|
||||||
|
self.assertIsNotNone(m)
|
||||||
|
|
||||||
|
#Die einzelnen Worte ausgeben
|
||||||
|
for word in m:
|
||||||
|
logging.debug(f' Wort: {word}')
|
||||||
|
|
||||||
|
|
||||||
|
# Test für Ersetzung (substitution von Tab mit Space)
|
||||||
|
def test_sub(self):
|
||||||
|
m = pattern_tab.sub(' ','Satz\tmit\tTabulator.')
|
||||||
|
logging.debug(f'm={m}')
|
||||||
|
|
||||||
|
# Test für einfache regular Expression ('O*')
|
||||||
|
def test_simple_re(self):
|
||||||
|
m = pattern_simple.search('Olli')
|
||||||
|
logging.debug(f'm={m.span()}')
|
||||||
|
self.assertTrue(m.end() > 0)
|
||||||
|
m = pattern_simple.search('Luana')
|
||||||
|
logging.debug(f'm={m.span()}')
|
||||||
|
self.assertFalse(m.end() >0)
|
||||||
|
|
||||||
|
# Test für den Iterator ('*Simpson')
|
||||||
|
def test_finditer(self):
|
||||||
|
m = pattern_simpson.finditer('Homer Simpson, Marge Simpson, Bart Simpson, Lisa Simpson, Maggie Simpson')
|
||||||
|
logging.debug(f'm={m}')
|
||||||
|
|
||||||
|
# Die einzelnen gefunden Teilstrings ausgeben.
|
||||||
|
for name in m:
|
||||||
|
logging.debug(f'Name={name},Start bei: {name.start()}')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
50
teil25/vornamen_reader.py
Normal file
50
teil25/vornamen_reader.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#encoding: utf-8
|
||||||
|
import re
|
||||||
|
|
||||||
|
def read_vornamen(filename):
|
||||||
|
dict = {}
|
||||||
|
# Der Zähler dient nur dazu, die erste Zeile zu überspringen
|
||||||
|
count = 0
|
||||||
|
pattern_csv = re.compile(';')
|
||||||
|
|
||||||
|
|
||||||
|
dict['mädchen'] = 0
|
||||||
|
dict['jungs'] = 0
|
||||||
|
dict['divers'] = 0
|
||||||
|
with open(filename,'r') as f:
|
||||||
|
for zeile in f:
|
||||||
|
if count >0:
|
||||||
|
# einzelne Zeile in seine Bestandteile zerlegen
|
||||||
|
splitted = pattern_csv.split(zeile.strip())
|
||||||
|
anzahl = splitted[0]
|
||||||
|
vorname = splitted[1]
|
||||||
|
geschlecht= splitted[2]
|
||||||
|
position = splitted[3]
|
||||||
|
|
||||||
|
if geschlecht == 'w':
|
||||||
|
dict['mädchen'] += 1
|
||||||
|
elif geschlecht == 'm':
|
||||||
|
dict['jungs'] += 1
|
||||||
|
else:
|
||||||
|
dict['divers'] += 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
data['vorname'] = vorname
|
||||||
|
data['anzahl'] = int(anzahl)
|
||||||
|
data['geschlecht'] = geschlecht
|
||||||
|
data['position'] = position
|
||||||
|
if vorname not in dict:
|
||||||
|
dict[vorname] = data
|
||||||
|
else:
|
||||||
|
# doppelte Einträge summieren wir auf.
|
||||||
|
e = dict[vorname]
|
||||||
|
e['anzahl'] = int(anzahl) + (e['anzahl'])
|
||||||
|
count +=1
|
||||||
|
|
||||||
|
gesamt = dict['jungs'] + dict['mädchen'] + dict['divers']
|
||||||
|
|
||||||
|
dict['gesamt'] = gesamt
|
||||||
|
return dict
|
||||||
|
|
7
teil26/square.py
Normal file
7
teil26/square.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
def square(x):
|
||||||
|
return x** 2
|
||||||
|
|
||||||
|
sq5 = square(5)
|
||||||
|
print(f'{sq5}')
|
5
teil26/square_lambda.py
Normal file
5
teil26/square_lambda.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
square = lambda x: x** 2
|
||||||
|
print(f'{square(5)}')
|
6
teil27/.gitignore
vendored
Normal file
6
teil27/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
example.py
|
||||||
|
ex2.py
|
||||||
|
*.log
|
||||||
|
__pycache__
|
||||||
|
db.ini
|
||||||
|
|
10
teil27/JSONFormatter.py
Normal file
10
teil27/JSONFormatter.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import logging
|
||||||
|
import logging.config
|
||||||
|
import json
|
||||||
|
ATTR_TO_JSON = ['created', 'filename', 'funcName', 'levelname', 'lineno', 'module', 'msecs', 'msg', 'name', 'pathname', 'process', 'processName', 'relativeCreated', 'thread', 'threadName']
|
||||||
|
class JsonFormatter:
|
||||||
|
def format(self, record):
|
||||||
|
obj = {attr: getattr(record, attr)
|
||||||
|
for attr in ATTR_TO_JSON}
|
||||||
|
return json.dumps(obj, indent=4)
|
||||||
|
|
8
teil27/db.ini.sample
Normal file
8
teil27/db.ini.sample
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[pidb]
|
||||||
|
host=database
|
||||||
|
user=piuser
|
||||||
|
password=<passwort>
|
||||||
|
database=pidb
|
||||||
|
|
||||||
|
|
||||||
|
|
75
teil27/dbhandler.py
Normal file
75
teil27/dbhandler.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# Datei dbhandler.py
|
||||||
|
import mysql.connector
|
||||||
|
import datetime
|
||||||
|
import configparser
|
||||||
|
import logging
|
||||||
|
from logging import config
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DBHandler(logging.Handler):
|
||||||
|
def __init__(self):
|
||||||
|
logging.Handler.__init__(self)
|
||||||
|
# Datenbank Konfiguration lesen
|
||||||
|
confparser = configparser.ConfigParser()
|
||||||
|
confparser.read('db.ini')
|
||||||
|
# Verbindung zur DB herstellen
|
||||||
|
self.connection= mysql.connector.connect(host=confparser['pidb']['host'],user = confparser['pidb']['user'],password = confparser['pidb']['password'],database = confparser['pidb']['database'])
|
||||||
|
# Tabelle anlegen, falls noch keine existiert.
|
||||||
|
self.connection.cursor().execute('''CREATE TABLE IF NOT EXISTS logs (
|
||||||
|
id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
zeit VARCHAR(50),
|
||||||
|
level VARCHAR(8),
|
||||||
|
message VARCHAR(40),
|
||||||
|
logger_name VARCHAR(25),
|
||||||
|
filename VARCHAR(60),
|
||||||
|
line INTEGER)''')
|
||||||
|
self.connection.commit()
|
||||||
|
|
||||||
|
# Bei Löschung der Klasseninstanz, Connection schliessen
|
||||||
|
def __del__(self):
|
||||||
|
if self.connection != None:
|
||||||
|
self.connection.close()
|
||||||
|
self.connection = None
|
||||||
|
|
||||||
|
# LogRecord in die DB schreiben
|
||||||
|
def emit(self, record):
|
||||||
|
try:
|
||||||
|
# Log-Daten in ein Tupel extrahieren
|
||||||
|
log_entry = (datetime.datetime.utcnow().isoformat(),
|
||||||
|
record.levelname,
|
||||||
|
record.getMessage(),
|
||||||
|
record.name,
|
||||||
|
record.pathname,
|
||||||
|
record.lineno)
|
||||||
|
|
||||||
|
# Log in die Datenbank einfügen
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
cursor.execute('''INSERT INTO logs (zeit, level, message, logger_name, filename, line)
|
||||||
|
VALUES (%s, %s, %s, %s, %s, %s)''', log_entry)
|
||||||
|
self.connection.commit()
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# im Fehlerfall den LogRecord nach "oben" weiterreichen.
|
||||||
|
self.handleError(record)
|
||||||
|
|
||||||
|
# Config aus JSON Datei laden und setzen
|
||||||
|
with open('handler_config.json') as file_config:
|
||||||
|
config.dictConfig(json.load(file_config))
|
||||||
|
# Logging testen
|
||||||
|
def testlogging():
|
||||||
|
print('testlogging() aufgerufen.')
|
||||||
|
logging.debug('Diese Zeile wird ausgefiltert.')
|
||||||
|
logging.debug('DEBUG/Druckdaten werden gesendet.')
|
||||||
|
logging.info('INFO/Es werden 2 Seiten gedruckt')
|
||||||
|
logging.debug('Diese Zeile wird auch ausgefiltert.')
|
||||||
|
logging.warning('WARN/nicht genügend Papier im Drucker')
|
||||||
|
logging.error('ERROR/Drucker nicht gefunden.')
|
||||||
|
logging.critical('CRITICAL/Drucker brennt')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
testlogging()
|
||||||
|
|
37
teil27/filterlogging.py
Normal file
37
teil27/filterlogging.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import logging
|
||||||
|
from logging import config
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Filter definieren
|
||||||
|
class DruckFilter(logging.Filter):
|
||||||
|
|
||||||
|
def __init__(self, params=None):
|
||||||
|
self.param = params
|
||||||
|
print('Druckfilter initialisiert')
|
||||||
|
|
||||||
|
def filter(self, record:logging.LogRecord)-> bool| logging.LogRecord:
|
||||||
|
|
||||||
|
# nur Text, der das Wort Druck enthält soll geloggt werden.
|
||||||
|
return record.getMessage().lower().find('druck') > -1
|
||||||
|
|
||||||
|
|
||||||
|
# Config aus JSON Datei laden und setzen
|
||||||
|
|
||||||
|
with open('log_config.json') as file_config:
|
||||||
|
config.dictConfig(json.load(file_config))
|
||||||
|
|
||||||
|
|
||||||
|
# Logging testen
|
||||||
|
def testlogging():
|
||||||
|
print('testlogging() aufgerufen.')
|
||||||
|
logging.debug('Diese Zeile wird ausgefiltert.')
|
||||||
|
logging.debug('DEBUG/Druckdaten werden gesendet.')
|
||||||
|
logging.info('INFO/Es werden 2 Seiten gedruckt')
|
||||||
|
logging.debug('Diese Zeile wird auch ausgefiltert.')
|
||||||
|
logging.warning('WARN/nicht genügend Papier im Drucker')
|
||||||
|
logging.error('ERROR/Drucker nicht gefunden.')
|
||||||
|
logging.critical('CRITICAL/Drucker brennt')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
testlogging()
|
||||||
|
|
41
teil27/halloween.py
Normal file
41
teil27/halloween.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#encoding: utf-8
|
||||||
|
import logging
|
||||||
|
from logging import config
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
import JSONFormatter
|
||||||
|
|
||||||
|
#JSON Formatter
|
||||||
|
ATTR_TO_JSON = ['created', 'filename', 'funcName', 'levelname', 'lineno', 'module', 'msecs', 'msg', 'name', 'pathname', 'process', 'processName', 'relativeCreated', 'thread', 'threadName']
|
||||||
|
class JsonFormatter:
|
||||||
|
def format(self, record):
|
||||||
|
obj = {attr: getattr(record, attr)
|
||||||
|
for attr in ATTR_TO_JSON}
|
||||||
|
return json.dumps(obj, indent=4)
|
||||||
|
|
||||||
|
#CustomFilter
|
||||||
|
|
||||||
|
class HalloweenFilter(logging.Filter):
|
||||||
|
|
||||||
|
def __init__(self, params=None):
|
||||||
|
self.param = params
|
||||||
|
print('Halloweenfilter initialisiert')
|
||||||
|
|
||||||
|
def filter(self, record:logging.LogRecord)-> bool| logging.LogRecord:
|
||||||
|
|
||||||
|
# Der Unsichtbare soll keine Spuren im Logfile hinterlassen.
|
||||||
|
return record.getMessage().lower().find('unsichtbar') == -1
|
||||||
|
|
||||||
|
visitors = ['Werwolf','Gespenst','Hexe','Unsichtbarer','Vampir','Dämon','Gorilla','Monster','Mumie']
|
||||||
|
|
||||||
|
treats = ['Bonbons','Twinkies','Lollis','Schokoladen','Kuchen', 'Äpfel']
|
||||||
|
|
||||||
|
secrets = random.SystemRandom()
|
||||||
|
|
||||||
|
with open('halloween_log_conf.json') as file_config:
|
||||||
|
config.dictConfig(json.load(file_config))
|
||||||
|
for v in visitors:
|
||||||
|
logging.info(f'An der Tür klopft eine gruselige Gestalt: {v}')
|
||||||
|
number = secrets._randbelow(20)
|
||||||
|
treat = secrets.choice(treats)
|
||||||
|
logging.info(f'Du gibst ihr {number} {treat} und sie zieht weiter')
|
37
teil27/halloween_log_conf.json
Normal file
37
teil27/halloween_log_conf.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"version":1,
|
||||||
|
"filters": {
|
||||||
|
"halloween":{
|
||||||
|
"()": "__main__.HalloweenFilter"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"formatters":{
|
||||||
|
"std_out":{
|
||||||
|
"format": "%(asctime)s : %(levelname)s : %(lineno)d : %(message)s",
|
||||||
|
"datefmt":"%I:%M:%S %d.%m.%Y"
|
||||||
|
},
|
||||||
|
"json": {
|
||||||
|
"()": "__main__.JsonFormatter"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"handlers":{
|
||||||
|
"console":{
|
||||||
|
"formatter": "std_out",
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"level": "DEBUG"
|
||||||
|
},
|
||||||
|
"file":{
|
||||||
|
"formatter":"json",
|
||||||
|
"class":"logging.FileHandler",
|
||||||
|
"level":"DEBUG",
|
||||||
|
"filename" : "halloween.log",
|
||||||
|
"filters": ["halloween"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root":{
|
||||||
|
"handlers":["console","file"],
|
||||||
|
"level": "DEBUG"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
33
teil27/handler_config.json
Normal file
33
teil27/handler_config.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"version":1,
|
||||||
|
"formatters":{
|
||||||
|
"std_out":{
|
||||||
|
"format": "%(asctime)s : %(levelname)s : %(module)s : %(funcName)s : %(lineno)d : (Process Details : (%(process)d, %(processName)s), Thread Details : (%(thread)d, %(threadName)s))\nLog : %(message)s",
|
||||||
|
"datefmt":"%d-%m-%Y %I:%M:%S"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"handlers":{
|
||||||
|
"console":{
|
||||||
|
"formatter": "std_out",
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"level": "DEBUG"
|
||||||
|
},
|
||||||
|
"db":{
|
||||||
|
"formatter": "std_out",
|
||||||
|
"()": "__main__.DBHandler",
|
||||||
|
"level": "DEBUG"
|
||||||
|
},
|
||||||
|
"file":{
|
||||||
|
"formatter":"std_out",
|
||||||
|
"class":"logging.FileHandler",
|
||||||
|
"level":"DEBUG",
|
||||||
|
"filename" : "raspithek.log"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root":{
|
||||||
|
"handlers":["console","file","db"],
|
||||||
|
"level": "DEBUG"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
35
teil27/log_config.json
Normal file
35
teil27/log_config.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"version":1,
|
||||||
|
"filters": {
|
||||||
|
"drucker":{
|
||||||
|
"()": "__main__.DruckFilter",
|
||||||
|
"params": "noshow"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"formatters":{
|
||||||
|
"std_out":{
|
||||||
|
"format": "%(asctime)s : %(levelname)s : %(module)s : %(funcName)s : %(lineno)d : (Process Details : (%(process)d, %(processName)s), Thread Details : (%(thread)d, %(threadName)s))\nLog : %(message)s",
|
||||||
|
"datefmt":"%d-%m-%Y %I:%M:%S"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"handlers":{
|
||||||
|
"console":{
|
||||||
|
"formatter": "std_out",
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"level": "DEBUG",
|
||||||
|
"filters": ["drucker"]
|
||||||
|
},
|
||||||
|
"file":{
|
||||||
|
"formatter":"std_out",
|
||||||
|
"class":"logging.FileHandler",
|
||||||
|
"level":"DEBUG",
|
||||||
|
"filename" : "raspithek.log"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root":{
|
||||||
|
"handlers":["console","file"],
|
||||||
|
"level": "DEBUG"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
52
teil27/testloggingconf.py
Normal file
52
teil27/testloggingconf.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import logging
|
||||||
|
from logging import config
|
||||||
|
|
||||||
|
# Logging Konfiguration definieren.
|
||||||
|
|
||||||
|
log_config = {
|
||||||
|
"version":1,
|
||||||
|
# root-Logger
|
||||||
|
"root":{
|
||||||
|
"handlers" : ["console",'file'],
|
||||||
|
"level": "DEBUG"
|
||||||
|
},
|
||||||
|
"handlers":{
|
||||||
|
#Handler für Console
|
||||||
|
"console":{
|
||||||
|
"formatter": "std_out",
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"level": "DEBUG"
|
||||||
|
},
|
||||||
|
# Handler für Logdatei
|
||||||
|
"file":{
|
||||||
|
"formatter":"std_out",
|
||||||
|
"class":"logging.FileHandler",
|
||||||
|
"level":"DEBUG",
|
||||||
|
"filename":"raspithek.log"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
# Format einer Logzeile
|
||||||
|
"formatters":{
|
||||||
|
"std_out": {
|
||||||
|
"format": "%(asctime)s : %(levelname)s : %(module)s : %(funcName)s : %(lineno)d : (Process Details : (%(process)d, %(processName)s), Thread Details : (%(thread)d, %(threadName)s))\nLog : %(message)s",
|
||||||
|
"datefmt":"%d-%m-%Y %I:%M:%S"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Config setzen
|
||||||
|
config.dictConfig(log_config)
|
||||||
|
|
||||||
|
# Logging testen
|
||||||
|
def testlogging():
|
||||||
|
print('testlogging() aufgerufen.')
|
||||||
|
logging.debug('DEBUG/Druckdaten werden gesendet.')
|
||||||
|
logging.info('INFO/Es werden 2 Seiten gedruckt')
|
||||||
|
logging.warning('WARN/nicht genügend Papier im Drucker')
|
||||||
|
logging.error('ERROR/Drucker nicht gefunden.')
|
||||||
|
logging.critical('CRITICAL/Drucker brennt')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
testlogging()
|
||||||
|
|
1
teil28/.gitignore
vendored
Normal file
1
teil28/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__pycache__
|
25
teil28/classdecor.py
Normal file
25
teil28/classdecor.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Datei: classdecor.py
|
||||||
|
|
||||||
|
|
||||||
|
def addrepr(cls):
|
||||||
|
# Universelle __repr__ Methode
|
||||||
|
def __repr__(self):
|
||||||
|
return f"{cls.__name__}({self.__dict__})"
|
||||||
|
cls.__repr__ = __repr__
|
||||||
|
|
||||||
|
return cls
|
||||||
|
|
||||||
|
@addrepr
|
||||||
|
class Fahrzeug():
|
||||||
|
def __init__(self,farbe,typ):
|
||||||
|
self.typ = typ
|
||||||
|
self.farbe = farbe
|
||||||
|
|
||||||
|
|
||||||
|
f1 = Fahrzeug('grau','VW')
|
||||||
|
f2 = Fahrzeug('rot','Ferrari')
|
||||||
|
|
||||||
|
print(f'{f1}')
|
||||||
|
print(f'{f2}')
|
||||||
|
|
||||||
|
|
13
teil28/counter.py
Normal file
13
teil28/counter.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#Datei: counter.py
|
||||||
|
|
||||||
|
def counter(func):
|
||||||
|
func.count = 0
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
func.count = func.count +1
|
||||||
|
print(f'{func.__name__} wurde {func.count}-mal aufgerufen.')
|
||||||
|
result = func(*args,**kwargs)
|
||||||
|
|
||||||
|
return result
|
||||||
|
wrapper.count = 0
|
||||||
|
return wrapper
|
||||||
|
|
16
teil28/fib.py
Normal file
16
teil28/fib.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#Datei: fib.py
|
||||||
|
|
||||||
|
import functools
|
||||||
|
import sys
|
||||||
|
from counter import counter
|
||||||
|
|
||||||
|
#@functools.cache
|
||||||
|
@counter
|
||||||
|
def fib(n):
|
||||||
|
if n in [0,1]:
|
||||||
|
return n
|
||||||
|
else:
|
||||||
|
return fib(n-1) + fib(n-2)
|
||||||
|
|
||||||
|
|
||||||
|
|
16
teil28/func_param.py
Normal file
16
teil28/func_param.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Datei: func_param.py
|
||||||
|
|
||||||
|
def add(x, y):
|
||||||
|
return x + y
|
||||||
|
|
||||||
|
def mul(x,y):
|
||||||
|
return x * y
|
||||||
|
|
||||||
|
def calculate(func, x, y):
|
||||||
|
return func(x, y)
|
||||||
|
|
||||||
|
result = calculate(add, 4, 6) # Aufruf von calculate mit add Funktion als Parameter
|
||||||
|
print(result) # Ausgabe ist 10
|
||||||
|
|
||||||
|
result = calculate(mul, 4, 6) # Aufruf von calculate mit add Funktion als Parameter
|
||||||
|
print(result) # Ausgabe ist 24
|
12
teil28/nested_function.py
Normal file
12
teil28/nested_function.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#Datei: nested_function.py
|
||||||
|
|
||||||
|
def print_message(message):
|
||||||
|
print('Umgebende Funktion')
|
||||||
|
def inner_function():
|
||||||
|
print('Eingebettete Funktion')
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
inner_function()
|
||||||
|
|
||||||
|
print_message("Irgendein Text")
|
||||||
|
|
20
teil28/pass_func.py
Normal file
20
teil28/pass_func.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
def make_pretty(func):
|
||||||
|
# define the inner function
|
||||||
|
def inner():
|
||||||
|
# add some additional behavior to decorated function
|
||||||
|
print("Dies ist die innere Funktion.")
|
||||||
|
|
||||||
|
# call original function
|
||||||
|
func()
|
||||||
|
# return the inner function
|
||||||
|
return inner
|
||||||
|
|
||||||
|
# define ordinary function
|
||||||
|
def ordinary():
|
||||||
|
print("Dies ist die ordinary() Funktion.")
|
||||||
|
|
||||||
|
# decorate the ordinary function
|
||||||
|
decorated_func = make_pretty(ordinary)
|
||||||
|
|
||||||
|
# call the decorated function
|
||||||
|
decorated_func()
|
17
teil28/reverse.py
Normal file
17
teil28/reverse.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
def reverse_decorator(func):
|
||||||
|
|
||||||
|
def wrapper(text):
|
||||||
|
make_reverse = "".join(reversed(text))
|
||||||
|
return func(make_reverse)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
@reverse_decorator
|
||||||
|
def format_message(text):
|
||||||
|
return f'Text: {text}'
|
||||||
|
|
||||||
|
print(format_message('Hallo'))
|
||||||
|
|
||||||
|
|
21
teil28/simpledecorator.py
Normal file
21
teil28/simpledecorator.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
def make_pretty(func):
|
||||||
|
# define the inner function
|
||||||
|
def inner():
|
||||||
|
# add some additional behavior to decorated function
|
||||||
|
print("I got decorated")
|
||||||
|
|
||||||
|
# call original function
|
||||||
|
func()
|
||||||
|
# return the inner function
|
||||||
|
return inner
|
||||||
|
|
||||||
|
# define ordinary function
|
||||||
|
@make_pretty
|
||||||
|
def ordinary():
|
||||||
|
print("I am ordinary")
|
||||||
|
|
||||||
|
# decorate the ordinary function
|
||||||
|
decorated_func = make_pretty(ordinary)
|
||||||
|
|
||||||
|
# call the decorated function
|
||||||
|
ordinary()
|
20
teil28/static.py
Normal file
20
teil28/static.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Datei static.py
|
||||||
|
|
||||||
|
class Math():
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add(x,y):
|
||||||
|
return x+y
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def sub(x,y):
|
||||||
|
return x-y
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mul(x,y):
|
||||||
|
return x*y
|
||||||
|
|
||||||
|
|
||||||
|
print(f'Add: {Math.add(3,2)}')
|
||||||
|
print(f'Sub: {Math.sub(3,2)}')
|
||||||
|
print(f'Mul: {Math.mul(3,2)}')
|
28
teil28/timer.py
Normal file
28
teil28/timer.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#Datei: timer.py
|
||||||
|
|
||||||
|
from fib import fib
|
||||||
|
from counter import counter
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def timer(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
result = func(*args,**kwargs)
|
||||||
|
|
||||||
|
end_time = time.time()
|
||||||
|
print(f'Methode {func.__name__} - Laufzeit {end_time - start_time:.4f}s')
|
||||||
|
return result
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def summe(n):
|
||||||
|
return f"Summe: {sum(range(n))}"
|
||||||
|
|
||||||
|
@timer
|
||||||
|
def calc_fib(n):
|
||||||
|
return fib(n)
|
||||||
|
|
||||||
|
print(summe(1000000))
|
||||||
|
print(calc_fib(int(sys.argv[1])))
|
4
teil29/.gitignore
vendored
Normal file
4
teil29/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# created by virtualenv automatically
|
||||||
|
bin
|
||||||
|
lib
|
||||||
|
|
1
teil29/.python-version
Normal file
1
teil29/.python-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.9
|
0
teil29/README.md
Normal file
0
teil29/README.md
Normal file
30
teil29/handleButton.py
Executable file
30
teil29/handleButton.py
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
#Datei: handleButton.py
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton
|
||||||
|
|
||||||
|
|
||||||
|
class MainWindow(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.setWindowTitle("Button Signal")
|
||||||
|
|
||||||
|
button = QPushButton("Bitte klicken")
|
||||||
|
button.setCheckable(True)
|
||||||
|
button.clicked.connect(self.handle_button_click)
|
||||||
|
|
||||||
|
# Set the central widget of the Window.
|
||||||
|
self.setCentralWidget(button)
|
||||||
|
|
||||||
|
def handle_button_click(self):
|
||||||
|
print("Button geklickt")
|
||||||
|
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
window = MainWindow()
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
app.exec()
|
6
teil29/hello.py
Normal file
6
teil29/hello.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
def main():
|
||||||
|
print("Hello from teil29!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
36
teil29/lineedit.py
Executable file
36
teil29/lineedit.py
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
#Datei: lineEdit.py
|
||||||
|
|
||||||
|
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QLineEdit, QVBoxLayout, QWidget
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class MainWindow(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.setWindowTitle("Eingabe mit LineEdit")
|
||||||
|
|
||||||
|
self.label = QLabel()
|
||||||
|
|
||||||
|
self.input = QLineEdit()
|
||||||
|
self.input.textChanged.connect(self.label.setText)
|
||||||
|
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
layout.addWidget(self.input)
|
||||||
|
layout.addWidget(self.label)
|
||||||
|
|
||||||
|
container = QWidget()
|
||||||
|
container.setLayout(layout)
|
||||||
|
|
||||||
|
# Set the central widget of the Window.
|
||||||
|
self.setCentralWidget(container)
|
||||||
|
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
window = MainWindow()
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
app.exec()
|
||||||
|
|
78
teil29/login.py
Executable file
78
teil29/login.py
Executable file
@@ -0,0 +1,78 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
#Datei: lineEdit.py
|
||||||
|
|
||||||
|
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QLineEdit, QPushButton, QGridLayout, QWidget
|
||||||
|
from PyQt6.QtGui import QPixmap
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class MainWindow(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.setWindowTitle("Login")
|
||||||
|
|
||||||
|
layout = QGridLayout()
|
||||||
|
layout.setContentsMargins(20, 20, 20, 20)
|
||||||
|
layout.setSpacing(10)
|
||||||
|
|
||||||
|
self.user_logo_pixmap =QPixmap('./user.jpg')
|
||||||
|
self.user_logo_label = QLabel()
|
||||||
|
self.user_logo_label.setPixmap(self.user_logo_pixmap)
|
||||||
|
|
||||||
|
layout.addWidget(self.user_logo_label,1,1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.user_label = QLabel('Username:')
|
||||||
|
self.password_label = QLabel('Passwort:')
|
||||||
|
self.username_input = QLineEdit()
|
||||||
|
self.password_input = QLineEdit()
|
||||||
|
self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
|
||||||
|
|
||||||
|
layout.addWidget(self.user_label,2,0)
|
||||||
|
layout.addWidget(self.username_input,2,1,1,2)
|
||||||
|
|
||||||
|
layout.addWidget(self.password_label,3,0)
|
||||||
|
layout.addWidget(self.password_input,3,1,1,2)
|
||||||
|
|
||||||
|
#Buttons
|
||||||
|
self.register_button = QPushButton("Register")
|
||||||
|
layout.addWidget(self.register_button, 4, 1)
|
||||||
|
|
||||||
|
self.login_button = QPushButton("Login")
|
||||||
|
self.login_button.clicked.connect(self.handle_login_button)
|
||||||
|
self.register_button.clicked.connect(self.handle_register_button)
|
||||||
|
|
||||||
|
layout.addWidget(self.login_button, 4, 2)
|
||||||
|
|
||||||
|
# Password vergessen
|
||||||
|
self.forgot_pw_button = QPushButton('Passwort vergessen')
|
||||||
|
self.forgot_pw_button.setStyleSheet('QPushButton {background-color: #A3C1DA; color: blue;}')
|
||||||
|
layout.addWidget(self.forgot_pw_button,5,2)
|
||||||
|
container = QWidget()
|
||||||
|
container.setLayout(layout)
|
||||||
|
|
||||||
|
# Set the central widget of the Window.
|
||||||
|
self.setCentralWidget(container)
|
||||||
|
|
||||||
|
def handle_register_button(self):
|
||||||
|
print('Register Button')
|
||||||
|
|
||||||
|
def handle_login_button(self):
|
||||||
|
print(f'Login mit {self.username_input.text()} and {self.password_input.text()}')
|
||||||
|
|
||||||
|
def handle_forgot_pw_button(self):
|
||||||
|
print('Forgot PW')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
window = MainWindow()
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
app.exec()
|
||||||
|
|
26
teil29/mainwindow.py
Executable file
26
teil29/mainwindow.py
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
#Datei: mainwindows.py
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from PyQt6.QtCore import QSize, Qt
|
||||||
|
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton
|
||||||
|
|
||||||
|
|
||||||
|
# Subclass QMainWindow to customize your application's main window
|
||||||
|
class MainWindow(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.setWindowTitle("My App")
|
||||||
|
button = QPushButton("Bitte klicken")
|
||||||
|
|
||||||
|
# Set the central widget of the Window.
|
||||||
|
self.setCentralWidget(button)
|
||||||
|
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
window = MainWindow()
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
app.exec()
|
12
teil29/pushbutton.py
Executable file
12
teil29/pushbutton.py
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
#Datei: pushbutton.py
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from PyQt6.QtWidgets import QApplication, QPushButton
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
window = QPushButton("Bitte klicken")
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
app.exec()
|
7
teil29/pyproject.toml
Normal file
7
teil29/pyproject.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[project]
|
||||||
|
name = "teil29"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
dependencies = []
|
8
teil29/pyvenv.cfg
Normal file
8
teil29/pyvenv.cfg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
home = /usr/bin
|
||||||
|
implementation = CPython
|
||||||
|
version_info = 3.11.2.final.0
|
||||||
|
virtualenv = 20.17.1+ds
|
||||||
|
include-system-site-packages = false
|
||||||
|
base-prefix = /usr
|
||||||
|
base-exec-prefix = /usr
|
||||||
|
base-executable = /usr/bin/python3
|
5
teil29/requirements.txt
Normal file
5
teil29/requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
numpy==2.2.3
|
||||||
|
opencv-python==4.11.0.86
|
||||||
|
PyQt6==6.8.1
|
||||||
|
PyQt6-Qt6==6.8.2
|
||||||
|
PyQt6_sip==13.10.0
|
30
teil29/sizewindow.py
Executable file
30
teil29/sizewindow.py
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
# Datei: sizewindow.py
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from PyQt6.QtCore import QSize, Qt
|
||||||
|
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton
|
||||||
|
|
||||||
|
|
||||||
|
# abgeleitet von QMainWindow können wir unser GUI besser einstellen und
|
||||||
|
# z.B. die Dimensionen des Fensters ändern.
|
||||||
|
class MainWindow(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.setWindowTitle("Fenstergröße")
|
||||||
|
|
||||||
|
button = QPushButton("Bitte klicken")
|
||||||
|
|
||||||
|
self.setFixedSize(QSize(400, 300))
|
||||||
|
|
||||||
|
# der Button sitzt als zentrales Widget im Fenster.
|
||||||
|
self.setCentralWidget(button)
|
||||||
|
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
window = MainWindow()
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
app.exec()
|
BIN
teil29/user.jpg
Normal file
BIN
teil29/user.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
23
teil29/window.py
Executable file
23
teil29/window.py
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
#Datei: window.py
|
||||||
|
|
||||||
|
# Die benötigten Qt Widgets
|
||||||
|
from PyQt6.QtWidgets import QApplication, QWidget
|
||||||
|
|
||||||
|
# Für die Kommandozeilenparameter
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# QTApplication instanziieren. Die Kommandozeilenparameter geben wir
|
||||||
|
# mit.
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
# Window Widget erzeugen
|
||||||
|
window = QWidget()
|
||||||
|
window.show() # Das Fenster muss immer manuell angzeigt werden.
|
||||||
|
|
||||||
|
# Wvent-Loop starten.
|
||||||
|
app.exec()
|
||||||
|
|
||||||
|
|
||||||
|
# So lang die Event-Loop läuft kommen wir hier nicht hin,
|
||||||
|
# sie kann durch den "Schließen" Button des Fensters unterbrochen werden.
|
10
walross/loop.py
Normal file
10
walross/loop.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Ohne Walross-Operator
|
||||||
|
n = 0
|
||||||
|
while n < 10:
|
||||||
|
n += 1
|
||||||
|
print(n)
|
||||||
|
|
||||||
|
# Mit Walross-Operator
|
||||||
|
n = 0
|
||||||
|
while (n := n + 1) <= 10:
|
||||||
|
print(n)
|
10
walross/simple_loop.py
Normal file
10
walross/simple_loop.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Ohne Walross-Operator
|
||||||
|
n = 0
|
||||||
|
while n < 10:
|
||||||
|
n += 1
|
||||||
|
print(n)
|
||||||
|
|
||||||
|
# Mit Walross-Operator
|
||||||
|
n = 0
|
||||||
|
while (n := n + 1) < 10:
|
||||||
|
print(n)
|
Reference in New Issue
Block a user