analitics

Pages

Saturday, July 18, 2020

Python Qt5 : Create a simple web browser.

This python package named PyQtWebEngine, see the official webpage for more infos:
The team development comes with this intro:
PyQtWebEngine is a set of Python bindings for The Qt Company’s Qt WebEngine framework. The framework provides the ability to embed web content in applications and is based on the Chrome browser. The bindings sit on top of PyQt5 and are implemented as three separate modules corresponding to the different libraries that make up the framework.
I used my python version: Python 3.8.3rc1 (tags/v3.8.3rc1:802eb67, Apr 29 2020, 21:39:14) [MSC v.1924 64 bit (AMD64)] on win32
... and PyQt5 version PyQt version: 5.15.0:
>>> from PyQt5.Qt import PYQT_VERSION_STR        
>>> print("PyQt version:", PYQT_VERSION_STR)  
PyQt version: 5.15.0
First, let's install this python package:
pip3 install PyQtWebEngine --user
Collecting PyQtWebEngine
  Using cached PyQtWebEngine-5.15.0-5.15.0-cp35.cp36.cp37.cp38-none-win_amd64.whl (57.9 MB)
Collecting PyQt5-sip<13>=12.8
  Using cached PyQt5_sip-12.8.0-cp38-cp38-win_amd64.whl (63 kB)
Collecting PyQt5>=5.15
  Using cached PyQt5-5.15.0-5.15.0-cp35.cp36.cp37.cp38-none-win_amd64.whl (64.5 MB)
Installing collected packages: PyQt5-sip, PyQt5, PyQtWebEngine
  WARNING: The scripts pylupdate5.exe, pyrcc5.exe and pyuic5.exe are installed in 
'C:\Users\catal\AppData\Roaming\Python\Python38\Scripts' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, 
use --no-warn-script-location.
Successfully installed PyQt5-5.15.0 PyQt5-sip-12.8.0 PyQtWebEngine-5.15.0
The WARNING reflects the path for this tool, but you can find on user folder, see:
C:\Users\catal>pylupdate5.exe
Usage:
    pylupdate5 [options] project-file
    pylupdate5 [options] source-files -ts ts-files

Options:
    -help  Display this information and exit
    -version
           Display the version of pylupdate5 and exit
    -verbose
           Explain what is being done
    -noobsolete
           Drop all obsolete strings
    -tr-function name
           name() may be used instead of tr()
    -translate-function name
           name() may be used instead of translate()

C:\Users\catal>
This is a simple source code with an browser example:
import sys
from PyQt5.Qt import *
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QWidget, QLabel, QLineEdit
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtCore import QSize, QUrl
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineView
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.setWindowTitle('catafest browser')

        self.browser_toolbar = QToolBar()
        self.addToolBar(self.browser_toolbar)
        self.back_button = QPushButton()
        #self.back_button.setIcon(QIcon('left.png'))
        self.back_button.clicked.connect(self.back_page)
        self.browser_toolbar.addWidget(self.back_button)
        self.forward_button = QPushButton()
        #self.forward_button.setIcon(QIcon('right.png'))
        self.forward_button.clicked.connect(self.forward_page)
        self.browser_toolbar.addWidget(self.forward_button)

        self.web_address = QLineEdit()
        self.web_address.returnPressed.connect(self.load_page)
        self.browser_toolbar.addWidget(self.web_address)

        self.web_browser = QWebEngineView()
        self.setCentralWidget(self.web_browser)
        first_url = "https://pypi.org/project/PyQt5/"

        self.web_address.setText(first_url)
        self.web_browser.load(QUrl(first_url))
        self.web_browser.page().titleChanged.connect(self.setWindowTitle)
        self.web_browser.page().urlChanged.connect(self.changed_page)
        
    def load_page(self):
        url = QUrl.fromUserInput(self.web_address.text())
        if url.isValid():
            self.web_browser.load(url)

    def back_page(self):
        self.web_browser.page().triggerAction(QWebEnginePage.Back)

    def forward_page(self):
        self.web_browser.page().triggerAction(QWebEnginePage.Forward)

    def changed_page(self, url):
        self.web_address.setText(url.toString())
        
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = MainWindow()
    availableGeometry = app.desktop().availableGeometry(mainWin)
    mainWin.resize(availableGeometry.width(), availableGeometry.height())
    mainWin.show()
    sys.exit( app.exec_() )

Wednesday, July 15, 2020

Python 3.8.3 : Lists in Python 3 - part 001.

I am currently working on a project that involves the use of complex data structures and lists and my time is limited.
This led me to start a new series of python tutorials on python lists.
I realized that the lists had no substantial changes in the evolution of the python programming language, see the official documentation.
You will find on the internet a lot of questions related to lists, algorithms, and problems involving lists.
If you are not a beginner then it will seem boring at first but over time I will try to draw attention to really significant elements in python programming with lists.
Let's start taking significant steps in using lists.
Before using the methods of list objects, let's create some lists:

# create a empty list 
my_list_001 = []
# fill the list with 4 consecutive numbers from 0 to 3 
my_list_001 = list(range(0,4))
# show the list 
my_list_001
[0, 1, 2, 3]
# set the variable n with value 4
n = 4
# create a list with 4 zeroes 
list_of_zeros = [0] * n
# show the list
listofzeros
[0, 0, 0, 0]
# import string python package 
import string
# create a string with all ascii letters
my_letters = string.ascii_letters
# use list to create a list with all letters
list(my_letters)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
# create a nested list is a list can also have another list as an item
my_list = ["catafest", [1,9,7,6], ["!"]]
# show the list
my_list
['catafest', [1, 9, 7, 6], ['!']]
# access elements from a list with index operator pozitive and negative [] 
my_list[0]
'catafest'
my_list[-1]
['!']
my_list[-2]
[1, 9, 7, 6]
my_list[-3]
'catafest'
# test conditions boolean
my_list[-3] == my_list[0]
True
my_list[-3] != my_list[0]
False
my_list_001[1] > listofzeros[1]
True
# sum an list element with another
sum_of_list_elemenet = my_list_001[1] + listofzeros[1]
# show result
sum_of_list_elemenet
1
# iterating through a list
for list_element in my_list:
...     print(list_element)
...
catafest
[1, 9, 7, 6]
['!']
# iterating each list  
for list_element in my_list:
...     for e in list_element:
...             print(e)
...
c
a
t
a
f
e
s
t
1
9
7
6
!
# create a list with all letters using chr and ord built-in functions
[chr(i) for i in range(ord('a'),ord('z')+1)]
# the result is
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
 'u', 'v', 'w', 'x', 'y', 'z']
# create a binary list from a integer
output = [int(x) for x in '{:08b}'.format(1976)]
# show the result of the list
output
[1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0]
# show the result just for on element of the list
output[3]
1
# convert a binary list to integer named result and set first with value 0
# using the bitwise left shift operator
result = 0
for digits in output:
    result = (result << 1) | digits
# show result of conversion from binary to integer
result
1976
# create a hexadecimal list from a list
hex_list = [hex(x) for x in my_list_001]
# show the hexadecimal list using the hex built-in function
hex_list
['0x0', '0x1', '0x2', '0x3']
# convert hexadecimal list to int list using the int 
int_list = [int(x,0) for x in hex_list]
# show the result
int_list
[0, 1, 2, 3]
# convert hexadecimal list to float list using the float.fromhex
float_list = [float.fromhex(x) for x in hex_list]
# show the result
float_list
[0.0, 1.0, 2.0, 3.0]
# create list using math python module 
import math
[2*x for x in my_list_001]
[0, 2, 4, 6]
[math.sin(x) for x in my_list_001]
[0.0, 0.8414709848078965, 0.9092974268256817, 0.1411200080598672]
# create sized list
sized_list = [1] * 4
# show the result
sized_list
[1, 1, 1, 1]
# list from 
>>> chars = ''.join(map(chr, range(32, 1048)))
>>> list(chars)
[' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5',
 '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a',
 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
 'x', 'y', 'z', '{', '|', '}', '~', '\x7f', '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', 
'\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f', '\x90', '\x91', '\x92', '\x93', '\x94', '\x95',
 '\x96', '\x97', '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f', '\xa0', '¡', '¢', '£', '¤', '¥',
 '¦', '§', '¨', '©', 'ª', '«', '¬', '\xad', '®', '¯', '°', '±', '²', '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»',
 '¼', '½', '¾', '¿', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò',
 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é',
 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ', 'Ā',
 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė',
 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į',
 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'ĸ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ',
 'ņ', 'Ň', 'ň', 'ʼn', 'Ŋ', 'ŋ', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ',
 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 
'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'ſ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƅ', 'ƅ', 'Ɔ', 'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ',
 'ƍ', 'Ǝ', 'Ə', 'Ɛ', 'Ƒ', 'ƒ', 'Ɠ', 'Ɣ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ', 'ƛ', 'Ɯ', 'Ɲ', 'ƞ', 'Ɵ', 'Ơ', 'ơ', 'Ƣ', 'ƣ',
...
...
 'ϗ', 'Ϙ', 'ϙ', 'Ϛ', 'ϛ', 'Ϝ', 'ϝ', 'Ϟ', 'ϟ', 'Ϡ', 'ϡ', 'Ϣ', 'ϣ', 'Ϥ', 'ϥ', 'Ϧ', 'ϧ', 'Ϩ', 'ϩ', 'Ϫ', 'ϫ', 'Ϭ', 'ϭ',
 'Ϯ', 'ϯ', 'ϰ', 'ϱ', 'ϲ', 'ϳ', 'ϴ', 'ϵ', '϶', 'Ϸ', 'ϸ', 'Ϲ', 'Ϻ', 'ϻ', 'ϼ', 'Ͻ', 'Ͼ', 'Ͽ', 'Ѐ', 'Ё', 'Ђ', 'Ѓ', 'Є',
 'Ѕ', 'І', 'Ї', 'Ј', 'Љ', 'Њ', 'Ћ', 'Ќ', 'Ѝ', 'Ў', 'Џ', 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З']
This is not all about create and convert list, but it is quite close to the reality of the lists.
This tutorial remains open due to the complex issue and maybe I will complete it in the future.

Monday, July 13, 2020

Python 3.8.3 : Short intro to Appium-Python-Client python package.

This is a short intro of the Appium-Python-Client python package and Appium based on Client-Server Architecture.
The Appium Server can be installed using two ways: using NPM or using Appium Desktop.
I download and run the desktop version from here.
Appium-windows-1.18.0-beta.1>Appium.exe
The latest version of Java, needed for Android Studio ( you can use the installation of Android Studio with SDK) and mobile phone set on USB debugging.
The next step is to set all settings for android into Appium interface:

Using appium server, you can send commands to the Appium Server which translates it to platform-specific commands and executes on the devices.
The Appium-Python-Client python package is an extension library for use with the mobile testing framework Appium, see the official webpage.
Install Appium-Python-Client python package with pip3 tool.
pip3 install Appium-Python-Client
Collecting Appium-Python-Client
...
Successfully built Appium-Python-Client
Installing collected packages: Appium-Python-Client
Successfully installed Appium-Python-Client-1.0.1
Now you can test this python package with Appium and simple examples.


Thursday, July 9, 2020

Python 3.8.3 : About aiohttp python package.

This python package can help you to writing single-threaded concurrent code using coroutines, multiplexing I/O access over sockets and other resources, running network clients and servers, and other related primitives, see the official documentation.
In this simple tutorial, I will show you in a few simple steps how to use it.
It is a complex module and there are multiple ways to use it.
First, on the Windows operating system users can install easily with:
pip3 install aiohttp
Collecting aiohttp
...
Installing collected packages: attrs, multidict, yarl, async-timeout, aiohttp
Successfully installed aiohttp-3.6.2 async-timeout-3.0.1 attrs-19.3.0 multidict-4.7.6 yarl-1.4.2
If you use a Linus operating system then you can use this command:
[mythcat@desk ~]$ pip3 install aiohttp --user 
...
Successfully installed aiohttp-3.6.2 async-timeout-3.0.1 multidict-4.7.5 yarl-1.4.2
This python package can be used as client or server.
The aiohttp.web implements a basic CLI for quickly serving an Application in development over TCP/IP.
You can find some example on this webpage.
These simple examples show how you can use handlers for web and servers and a request handler with a coroutine.
[mythcat@desk ~]$ python3 
Python 3.7.6 (default, Jan 30 2020, 09:44:41) 
[GCC 9.2.1 20190827 (Red Hat 9.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from aiohttp import web 
>>> def handler_req(request):
...     return web.Response(text='Handler')
... 
>>> handler_req
<function 0x7fc8a76aab00="" at="" handler_req="">
>>> async def handler_req_async(request):
...     return web.Response(text='async Handler')
... 
>>> handler_req_async
<function+0x7fc8a574edd0...
>>> import aiohttp
>>> from aiohttp import web
>>> from aiohttp.client import _RequestContextManager
>>> async def test_await(test_server, loop):
...  
...     async def handler(request):
...         return web.HTTPOk()
...
...     app = web.Application(loop=loop)
...     app.router.add_route('GET', '/', handler)
...     server = await test_server(app)
...     resp = await aiohttp.get(server.make_url('/'), loop=loop)
...     assert resp.status == 200
...     assert resp.connection is not None
...     await resp.release()
...     assert resp.connection is None
>>> test_await('htthttp://localhost:8080/',1000)   
<coroutine object test_await at 0x00000261FB96EA40>
Let's see the output of the dir:
dir(aiohttp)
['AsyncIterablePayload', 'AsyncResolver', 'BadContentDispositionHeader', 'BadContentDispositionParam', 
'BaseConnector', 'BasicAuth', 'BodyPartReader', 'BufferedReaderPayload', 'BytesIOPayload', 'BytesPayload',
 'ChainMapProxy', 'ClientConnectionError', 'ClientConnectorCertificateError', 'ClientConnectorError', 
'ClientConnectorSSLError', 'ClientError', 'ClientHttpProxyError', 'ClientOSError', 'ClientPayloadError', 
'ClientProxyConnectionError', 'ClientRequest', 'ClientResponse', 'ClientResponseError', 'ClientSSLError', 
'ClientSession', 'ClientTimeout', 'ClientWebSocketResponse', 'ContentTypeError', 'CookieJar', 'DataQueue', 
'DefaultResolver', 'DummyCookieJar', 'EMPTY_PAYLOAD', 'EofStream', 'Fingerprint', 'FlowControlDataQueue', 
'FormData', 'HttpVersion', 'HttpVersion10', 'HttpVersion11', 'IOBasePayload', 'InvalidURL', 'JsonPayload', 
'MultipartReader', 'MultipartWriter', 'NamedPipeConnector', 'PAYLOAD_REGISTRY', 'Payload', 'RequestInfo', 
'ServerConnectionError', 'ServerDisconnectedError', 'ServerFingerprintMismatch', 'ServerTimeoutError', 
'Signal', 'StreamReader', 'StringIOPayload', 'StringPayload', 'TCPConnector', 'TextIOPayload', 
'ThreadedResolver', 'TooManyRedirects', 'TraceConfig', 'TraceConnectionCreateEndParams', 
'TraceConnectionCreateStartParams', 'TraceConnectionQueuedEndParams', 'TraceConnectionQueuedStartParams', 
'TraceConnectionReuseconnParams', 'TraceDnsCacheHitParams', 'TraceDnsCacheMissParams', 
'TraceDnsResolveHostEndParams', 'TraceDnsResolveHostStartParams', 'TraceRequestChunkSentParams', 
'TraceRequestEndParams', 'TraceRequestExceptionParams', 'TraceRequestRedirectParams', 'TraceRequestStartParams',
 'TraceResponseChunkReceivedParams', 'Tuple', 'UnixConnector', 'WSCloseCode', 'WSMessage', 'WSMsgType', 
'WSServerHandshakeError', 'WebSocketError', '__all__', '__builtins__', '__cached__', '__doc__', '__file__',
 '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', 'abc', 'base_protocol', 
'client', 'client_exceptions', 'client_proto', 'client_reqrep', 'client_ws', 'connector', 
'content_disposition_filename', 'cookiejar', 'formdata', 'frozenlist', 'get_payload', 'hdrs', 'helpers', 
'http', 'http_exceptions', 'http_parser', 'http_websocket', 'http_writer', 'locks', 'log', 'multipart', 
'parse_content_disposition', 'payload', 'payload_streamer', 'payload_type', 'request', 'resolver', 'signals', 
'streamer', 'streams', 'tcp_helpers', 'tracing', 'typedefs']

Saturday, June 27, 2020

Python 3.8.3 : PyCryptodome python package - part 001.

In the last tutorial, I wrote on Sunday, June 16, 2019, you can see a simple example of this python package with KDF with PBKDF2 function.
I guess it should be interesting for visitors to this blog to read more about this package because it is very useful and interesting.
Today I come up with another tutorial covering how to use A.E.S. standard encryption and decrypting text in a binary file.
The A.E.S. is a standard?
The Federal Information Processing Standards Publications (FIPS PUBS) announcing the A.E.S. on November 26, 2001, on the Federal Information Processing Standards Publication 197.
A.E.S. known as Advanced Encryption Standard is a symmetric block cipher standardized by NIST.
The N.I.S.T is an abbreviation National Institute of Standards and Technology.
This python package named PyCryptodome is a self-contained Python package of low-level cryptographic primitives, see the readthedocs.io webpage.
First, you need to see if this python package is not on conflict with another one named PyCrypto.
Then use pip3 tool to install.
pip3 uninstall PyCrypto
WARNING: Skipping PyCrypto as it is not installed.
...
pip3 install pycryptodome
Collecting pycryptodome
...
Installing collected packages: pycryptodome
Successfully installed pycryptodome-3.9.8
Here is the source code commented for a better understanding of the encryption and decryption steps.
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes

# the data input needs to be encoded, else you will receive this error
# python TypeError: Object type  cannot be passed to C code

data = "Hello World! by catafest!".encode("utf8")
# first step - prepare for encrypt
key = get_random_bytes(16)
print("print key is: ", key)
cipher = AES.new(key, AES.MODE_EAX)
print("print cipher is: ", cipher)
ciphertext, tag = cipher.encrypt_and_digest(data)
print("print ciphertext is: ", ciphertext)

# open the binary file 
file_out = open("AES_encrypted.bin", "wb")
# write to binary file 
[ file_out.write(x) for x in (cipher.nonce, tag, ciphertext) ]

# the file is close 
file_out.close()

# next step - prepare for decrypt
new_cipher = AES.new(key, AES.MODE_EAX, cipher.nonce)

# open again the binary file 
file_in = open("AES_encrypted.bin", "rb")
# read all data from file
nonce, tag, ciphertext = [file_in.read(x) for x in (16, 16, -1) ]
# the file is close 
file_out.close()

# show data from file
print("print nonce is: ", nonce)
print("print tag is: ", tag)
print("print ciphertext is: ", ciphertext)

# create a new cipher
cipher = AES.new(key, AES.MODE_EAX, nonce)

# use this to decrypt
data = cipher.decrypt_and_verify(ciphertext, tag)
# show the result 
print(data)
The result of running the python script is this:
python.exe .\pycryptodome_AES_001.py
print key is:  b'\xbdEX\xf8\x1d!\xc5\xceI\x87\x81\xf1\xd5\xba\x8c\r'
print cipher is:  <Crypto.Cipher._mode_eax.EaxMode object at 0x000001D5F32DE100>
print cipher is:  <Crypto.Cipher._mode_eax.EaxMode object at 0x000001E062AFE100>
print ciphertext is:  b'ON\x1d\xb9\xb7\xa8\xf5\xd6\x0c\x91\xc5`B\xf4\x95u\xe1D\xb5\x88&I\x15\xc5\xc5'
print nonce is:  b'3\xa6R8\xbb\n \x9cimp$\xe4\xee\xf5-'
print tag is:  b'\xb8)\xe4\xe7\x08uE~\x84s]\xedX\xf5\xf9\xea'
print ciphertext is:  b'ON\x1d\xb9\xb7\xa8\xf5\xd6\x0c\x91\xc5`B\xf4\x95u\xe1D\xb5\x88&I\x15\xc5\xc5'
b'Hello World! by catafest!'
You can read about this process on this website.

Python 2.7.10 : IronPython and C# with Dynamic Language Runtime.

This is a simple tutorial about python and C# using the Dynamic Language Runtime with IronPython.
I use Visual Studio 2019 and .NET Framework 4.7.2 with my Console C# project named DynamicLanguageRuntime_001.
Let's install the package with Visual Studio by open the console using the main menu: Tools - NuGet Package Manager - Package Manager Console command.
PM> Install-Package DynamicLanguageRuntime
Package 'DynamicLanguageRuntime.1.2.3' already exists in project 'DynamicLanguageRuntime_001'
Time Elapsed: 00:00:01.2208674
Use Solution Explorer use right-click on References item from your project and use Add Reference ...
Into the new window dialog named Reference Manager on the Assemblies - Framework uses the edit box to search IronPython.
Then use the checkbox to select these two options: IronPython and IronPython.Modules.
See the screenshot from Visual Studio I.D.E.:

This is the source code I used:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IronPython.Hosting;
using IronPython.Runtime;
using IronPython;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting;

namespace DynamicLanguageRuntime_001
{
    class Program
    {
        static void Main(string[] args)
        {
            // create python engine 
            ScriptEngine engine = Python.CreateEngine();
            // get and add paths to enfine
            var python_search_paths = engine.GetSearchPaths();
            python_search_paths.Add(@"C:\Program Files\IronPython 2.7\Lib");
            engine.SetSearchPaths(python_search_paths);
            // create a scope 
            ScriptScope scope = engine.CreateScope();
            // using CreateScriptSourceFromString
            engine.CreateScriptSourceFromString("print '... simple example with ironpython and C#'").Execute();
            // using Execute
            engine.Execute("print '                             by catafest!'", scope);
            // using ExecuteFile
            engine.ExecuteFile(@"D:\Projects\Python\testing\test_webpage_001.py", scope);
            dynamic testFunction = scope.GetVariable("GetFriends");
            var result = testFunction();
        }
    }
} 

Friday, June 26, 2020

Python 3.6.9 : My colab tutorials - part 005.

Today I tested google colab python features with google authentification and google.colab drive and files.
The first part of google colab code comes with authentification and you need to add the verification code for google account.
The google colab use the same version of python:
3.6.9 (default, Apr 18 2020, 01:56:04) [GCC 8.4.0]
You can see all source code on my GitHub account.
The notebook can be found here.

Sunday, June 21, 2020

Python 3.8.3 : Using twitter application with python-twitter - part 002.

This is the second part of tutorials series with python-twitter.
Today I will show you how to get pieces of information about friends, users and save into a binary file with pickle known as cPickle.
I will use my old source code from the last tutorial.
import os
import twitter
# for save to file import by python version
try:
   import cPickle as pickle
except:
   import pickle

consumer_key=' '
consumer_secret=' '
token_key=' '
token_secret=' '

if __name__ == "__main__":
    api = twitter.Api(consumer_key=consumer_key,
                  consumer_secret=consumer_secret,
                  access_token_key=token_key,
                  access_token_secret=token_secret) 
    
    screen_name = 'catafest'
       
    # print all users of this account authentificated 
    # you can use GetFriends(screen_name=screen_name) 
    users = api.GetFriends()
    
    print([u.screen_name for u in users])
    # get followers 
    followers = api.GetFollowers(screen_name=screen_name)
    # print followers 
    print([f.screen_name for f in followers])
    
    # ... and save into a binary file 
    followers_file = "followers_file.bin"
    
    if not os.path.exists(followers_file):
        pickle.dump(followers, open(followers_file, "wb"), protocol=pickle.HIGHEST_PROTOCOL)
        
    # load binary file     
    if os.path.exists(followers_file):
        followers_read = pickle.load(open(followers_file, "rb"))
        print(followers_read)
The result is similar with this:
python.exe .\test_webpage_001.py
['SnapChick', 'NASA', 'andor_saga', 'blendermarket', 'Minehut', 'Aternos', 'axnro', 'Flexi23',
...
['PStackoverflow', 'SamLeac86078418', 'Sohanurr559', 'jasonalba', 'avkorablev', 'dotnetfiddle',
...
[User(ID=1260415029855256583, ScreenName=PStackoverflow), 
...

Saturday, June 20, 2020

Python 3.8.3 : Using twitter application with python-twitter - part 001.

You need to create a application for your twitter user developer on this webpage.
The next step is to get all keys and tokens from your application.
I used the python-twitter see the official webpage documentation.
Let's install this python module using the pip tool
pip install python-twitter
Collecting python-twitter
...
Installing collected packages: oauthlib, requests-oauthlib, python-twitter
Successfully installed oauthlib-3.1.0 python-twitter-3.5 requests-oauthlib-1.3.0
Let's see a simple source code:
import os
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import twitter
import datetime
from datetime import *

consumer_key=' '
consumer_secret=' '
token_key=' '
token_secret=' '

def get_tweets(api=None, screen_name=None):
    timeline = api.GetUserTimeline(screen_name=screen_name, count=200)
    earliest_tweet = min(timeline, key=lambda x: x.id).id
    print("getting tweets before:", earliest_tweet)

    while True:
        tweets = api.GetUserTimeline(
            screen_name=screen_name, max_id=earliest_tweet, count=200
        )
        new_earliest = min(tweets, key=lambda x: x.id).id

        if not tweets or new_earliest == earliest_tweet:
            break
        else:
            earliest_tweet = new_earliest
            print("getting tweets before:", earliest_tweet)
            timeline += tweets

    return timeline

if __name__ == "__main__":
    api = twitter.Api(consumer_key=consumer_key,
                  consumer_secret=consumer_secret,
                  access_token_key=token_key,
                  access_token_secret=token_secret) 
    # print api 
    #print(dir(api))
    
    # print all users of this account authentificated 
    #users = api.GetFriends()
    #print([u.screen_name for u in users])
    
    # print all tweets of my user catafest 
    screen_name = "catafest"
    timeline = get_tweets(api=api, screen_name=screen_name)
    dates = []
    for x in timeline:
        created = x.created_at
        dates.append(created)
        
    print(dates)
    dat = [datetime.strptime(d, "%a %b %d %H:%M:%S +0000 %Y") for d in dates]

    levels = np.tile([-8, 8, -4, 4, -1, 1],int(np.ceil(len(dat)/3)))[:len(dat)]
    print(levels)
    fig, ax = plt.subplots(figsize=(7.6, 5), constrained_layout=True)
    ax.set(title="Twitter dates")
    markerline, stemline, baseline = ax.stem(dat, levels,linefmt="C3-", basefmt="k-",use_line_collection=True)
    markerline.set_ydata(np.zeros(len(dat)))
    plt.setp(markerline, mec="k", mfc="w", zorder=1)
    plt.show()
The result of this script comes with this output:
python .\test_webpage_001.py
getting tweets before: 1123237192422367234
['Mon May 18 13:52:09 +0000 2020', 'Sat May 09 11:14:43 +0000 2020', 'Fri May 08 10:42:18 +0000 2020', 
'Fri May 08 10:41:37 +0000 2020', 'Sat May 02 17:41:07 +0000 2020', 'Sat May 02 17:39:15 +0000 2020', 
'Thu Apr 30 12:53:48 +0000 2020', 'Tue Apr 28 20:00:38 +0000 2020', 'Mon Apr 27 21:12:07 +0000 2020', 
'Fri Apr 24 16:39:58 +0000 2020', 'Fri Apr 24 16:09:26 +0000 2020', 'Sat Apr 11 16:56:40 +0000 2020', 
'Sun Mar 22 19:11:16 +0000 2020', 'Sat Mar 21 09:03:30 +0000 2020', 'Sat Mar 21 09:02:48 +0000 2020', 
'Sat Mar 21 08:59:18 +0000 2020', 'Mon Mar 16 06:29:34 +0000 2020', 'Fri Jan 24 19:59:38 +0000 2020', 
'Sat Jan 18 12:14:07 +0000 2020', 'Fri Jan 17 20:58:18 +0000 2020', 'Thu Jan 16 20:50:47 +0000 2020', 
'Thu Jan 16 20:49:16 +0000 2020', 'Fri Jan 03 17:57:33 +0000 2020', 'Sat Dec 28 10:14:11 +0000 2019', 
'Tue Apr 30 14:46:30 +0000 2019']
[-8  8 -4  4 -1  1 -8  8 -4  4 -1  1 -8  8 -4  4 -1  1 -8  8 -4  4 -1  1 -8]
The image show with matplotlib is this:

Python 3.7.5 : Django on Fedora distro.

[mythcat@desk django]$ source env/bin/activate
(env) [mythcat@desk django]$ python3 
Python 3.7.6 (default, Dec 19 2019, 22:52:49) 
[GCC 9.2.1 20190827 (Red Hat 9.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.VERSION
(3, 0, 1, 'final', 1) 

Static files are those files that can not be processed, generated or modified by the server.
Static files improve the performance of the website with the template inheritance method.
Static file management is an important factor in web development.
I will show you how static file works on Django project.
The new static files folder is set on settings.py file:
...
# Static files (CSS, JavaScript, Images)

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, '/home/mythcat/projects/django/mysite/test001/')
STATICFILES_DIRS = [
   os.path.join(BASE_DIR, 'static'),
 ]
...
Let's run the server:
(env) [mythcat@desk mysite]$ python3 manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
January 26, 2020 - 09:01:10
Django version 3.0.1, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C. 
If I try to use the admin area then we can see the bad result for static files. 
...
[26/Jan/2020 09:10:02] "GET /admin/test001/post/ HTTP/1.1" 200 5935
[26/Jan/2020 09:10:02] "GET /static/admin/css/changelists.css HTTP/1.1" 200 6190
[26/Jan/2020 09:10:02] "GET /admin/jsi18n/ HTTP/1.1" 200 3223
[26/Jan/2020 09:10:02] "GET /static/admin/js/jquery.init.js HTTP/1.1" 200 363
[26/Jan/2020 09:10:02] "GET /static/admin/js/urlify.js HTTP/1.1" 200 8941
[26/Jan/2020 09:10:02] "GET /static/admin/js/actions.js HTTP/1.1" 200 6766
[26/Jan/2020 09:10:02] "GET /static/admin/js/prepopulate.js HTTP/1.1" 200 1530
[26/Jan/2020 09:10:02] "GET /static/admin/js/core.js HTTP/1.1" 200 5723
[26/Jan/2020 09:10:02] "GET /static/admin/js/admin/RelatedObjectLookups.js HTTP/1.1" 200 6918
[26/Jan/2020 09:10:02] "GET /static/admin/css/fonts.css HTTP/1.1" 200 423
[26/Jan/2020 09:10:02] "GET /static/admin/js/vendor/jquery/jquery.js HTTP/1.1" 200 280364
[26/Jan/2020 09:10:02] "GET /static/admin/js/vendor/xregexp/xregexp.js HTTP/1.1" 200 128820
[26/Jan/2020 09:10:02] "GET /static/admin/img/tooltag-add.svg HTTP/1.1" 200 331
[26/Jan/2020 09:10:02] "GET /static/admin/img/sorting-icons.svg HTTP/1.1" 200 1097
Not Found: /favicon.ico
... 
Now I can try to run the command collectstatic.
When this command is executed, Django performs these operations:
  • it looks for static files in all the directories listed in STATICFILES_DIRS;
  • the static-files are then copied and saved in STATIC_ROOT directory;
  • when the server is requested for static content, it will fetch a file from STATIC_ROOT;
  • that file will have its URL modified with STATIC_URL.
These errors show us many informations about this process:
 (env) [mythcat@desk mysite]$ python3 manage.py collectstatic

You have requested to collect static files at the destination
location as specified in your settings:

    /home/mythcat/projects/django/mysite

This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: yes
Found another file with the destination path 'admin/js/urlify.js'. It will be ignored since only the first 
encountered file is collected. If this is not what you want, make sure every static file has a unique path.
...
Found another file with the destination path 'django.png'. It will be ignored since only the first 
encountered file is collected. If this is not what you want, make sure every static file has a unique path.
Found another file with the destination path 'favicon.ico'. It will be ignored since only the first 
encountered file is collected. If this is not what you want, make sure every static file has a unique path.
Found another file with the destination path 'admin/js/urlify.js'. It will be ignored since only the first 
encountered file is collected. If this is not what you want, make sure every static file has a unique path.
...

Found another file with the destination path 'rest_framework/js/prettify-min.js'. 
It will be ignored since only the first encountered file is collected. If this is not what you want, make
 sure every static file has a unique path.
...
166 static files copied to '/home/mythcat/projects/django/mysite'. 
But, Django respects the order of your applications in settings.py file the INSTALLED_APPS area, when running collectstatic command.
If you have two installed apps that write the same static files then Django collectstatic command will write the static files for the app appearing first in the list.
In my case: django.contrib.admin , test001 and ... .
Also, is need to set this code source on urls.py to return the proper URL pattern for serving static files to your already defined pattern list.
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
...
urlpatterns += staticfiles_urlpatterns()
Let's run the runserver:
 (env) [mythcat@desk mysite]$ python3 manage.py runserver
...
[26/Jan/2020 09:29:18] "GET /static/admin/css/fonts.css HTTP/1.1" 200 423
Not Found: /favicon.ico 
You can see the /favicon.ico is not found in the default path and need to move it at /home/mythcat/projects/django/mysite/test001.
After these changes let's fix all the problems I created with these learning steps on static issues.
Let's move the static folder into mysite folder.
Change the settings.py file for the static issue with this source of code:
# Static files (CSS, JavaScript, Images)

STATIC_URL = '/static/'

STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_DIRS = [
   os.path.join(BASE_DIR, 'static'),
 ]
Run the (env) [mythcat@desk mysite]$ python3 manage.py collectstatic
(env) [mythcat@desk mysite]$ python3 manage.py collectstatic

You have requested to collect static files at the destination
location as specified in your settings:

    /home/mythcat/projects/django/mysite/static

This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: yes

163 static files copied to '/home/mythcat/projects/django/mysite/static', 2 unmodified.
(env) [mythcat@desk mysite]$ ls
db.sqlite3  favicon.ico  manage.py  mysite  rest_framework  static  test001
(env) [mythcat@desk mysite]$ cd static/
(env) [mythcat@desk static]$ ls
admin  django.png  favicon.ico  rest_framework
This is a simple base tutorial.
In this point you can select the way of your Django project.

Wednesday, June 17, 2020

Python 3.8.2 : Create a Django Calendar - part 002.

I was a bit busy with another project I am working on and this is the reason that led to the delay of this tutorial.
The big problem with Django tutorials is the volume of the source code.
Because of this, this tutorial will highlight changes to the source code and share it in my GitHub account.
Let's see the changes into my project tree and files:
└───test_calendar
    ├───first_calendar
    │   ├───migrations
    │   └───static
    │       └───first_calendar
    │           └───css
    ├───media
    ├───templates
    └───test_calendar
The settings.py file:
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'first_calendar.apps.FirstCalendarConfig',
]
...
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, '/static/')
]

STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
The complete project is a basic calendar, which can be modified by adding events or linked to a Google calendar.
The source code can be found here.

Saturday, June 13, 2020

Python 3.8.2 : Create a Django Calendar - part 001.

This tutorial show you how can use pipenv tool and set the Django project in order to create a calendar with Django project.
First, install the pipenv tool using the pip tool:
python -m pip install pipenv
Collecting pipenv
...
Successfully installed pipenv-2020.6.2 virtualenv-clone-0.5.4
You can see all options and features with this command:
pipenv
Usage: pipenv [OPTIONS] COMMAND [ARGS]...

Options:
  --where                         Output project home information.
  --venv                          Output virtualenv information.
  --py                            Output Python interpreter information.
  --envs                          Output Environment Variable options.
  --rm                            Remove the virtualenv.
  --bare                          Minimal output.
  --completion                    Output completion (to be executed by the
                                  shell).

  --man                           Display manpage.
  --support                       Output diagnostic information for use in
                                  GitHub issues.

  --site-packages / --no-site-packages
                                  Enable site-packages for the virtualenv.
                                  [env var: PIPENV_SITE_PACKAGES]

  --python TEXT                   Specify which version of Python virtualenv
                                  should use.

  --three / --two                 Use Python 3/2 when creating virtualenv.
  --clear                         Clears caches (pipenv, pip, and pip-tools).
                                  [env var: PIPENV_CLEAR]

  -v, --verbose                   Verbose mode.
  --pypi-mirror TEXT              Specify a PyPI mirror.
  --version                       Show the version and exit.
  -h, --help                      Show this message and exit.


Usage Examples:
   Create a new project using Python 3.7, specifically:
   $ pipenv --python 3.7

   Remove project virtualenv (inferred from current directory):
   $ pipenv --rm

   Install all dependencies for a project (including dev):
   $ pipenv install --dev

   Create a lockfile containing pre-releases:
   $ pipenv lock --pre

   Show a graph of your installed dependencies:
   $ pipenv graph

   Check your installed dependencies for security vulnerabilities:
   $ pipenv check

   Install a local setup.py into your virtual environment/Pipfile:
   $ pipenv install -e .

   Use a lower-level pip command:
   $ pipenv run pip freeze

Commands:
  check      Checks for PyUp Safety security vulnerabilities and against PEP
             508 markers provided in Pipfile.

  clean      Uninstalls all packages not specified in Pipfile.lock.
  graph      Displays currently-installed dependency graph information.
  install    Installs provided packages and adds them to Pipfile, or (if no
             packages are given), installs all packages from Pipfile.

  lock       Generates Pipfile.lock.
  open       View a given module in your editor.
  run        Spawns a command installed into the virtualenv.
  shell      Spawns a shell within the virtualenv.
  sync       Installs all packages specified in Pipfile.lock.
  uninstall  Uninstalls a provided package and removes it from Pipfile.
  update     Runs lock, then sync.
Create a folder for your project, I used this folder named django_test_002:
mkdir django_test_002
Create a virtualenv using the pipenv shell
django_test_002>pipenv shell
Creating a virtualenv for this project…
Pipfile: D:\Projects\Python\django_test_002\Pipfile
Using D:/Python38/python.exe (3.8.2) to create virtualenv…
...
Install Django python package:
(django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002> pipenv install Django
Installing Django…
Adding Django to Pipfile's [packages]…
Installation Succeeded
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
 Locking...Building requirements...
Resolving dependencies...
Success!
Updated Pipfile.lock (a6086c)!
Installing dependencies from Pipfile.lock (a6086c)…
  ================================ 0/0 - 00:00:00
Let's test the pipenv shell tool with a simple example for activate, deactivate and exit:
D:\Projects\Python\django_test_002>pipenv shell
Launching subshell in virtual environment…
Microsoft Windows [Version 10.0.18363.900]
(c) 2019 Microsoft Corporation. All rights reserved.

(django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002>activate

(django_test_002) (django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002>deactivate
(django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002>exit
Stores all the python packages you installed into a requirements.txt file
D:\Projects\Python\django_test_002>pipenv shell
Launching subshell in virtual environment…
Microsoft Windows [Version 10.0.18363.900]
(c) 2019 Microsoft Corporation. All rights reserved.

(django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002>pip3 freeze > requirements.txt
Create django project named test_calendar:
(django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002>django-admin startproject test_calendar
Start server to check that our project is running at localhost:8000.
(django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002>cd test_calendar

(django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002\test_calendar>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations 
for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
June 13, 2020 - 20:52:00
Django version 3.0.7, using settings 'test_calendar.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Now, you can open with your browser the default link http://127.0.0.1:8000/ and you will see the start page of Django framework.
Use Ctrl+C keys to stop it, and create an application.
I used the next command to create first_calendar application.
D:\Projects\Python\django_test_002\test_calendar>python manage.py startapp first_calendar
Into the folder application first_calendar make these changes to views.py from to create a index view:
from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.

def index(request):
    return HttpResponse('hello')
Create a new file named urls.py in the folder first_calendar and add this source code:
from django.conf.urls import url
from . import views

app_name = 'first_calendar'
urlpatterns = [
    #url(r'^index/$', views.index, name='index'),
    url('', views.index,  name='index'),
]
Return to the project base folder and add the view to urls.py from the project test_calendar folder:
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('first_calendar.urls')),
]
Into the project folder test_calendar add the application to the file settings.py.
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'first_calendar',
]
Use migrate option to migrate the project:
(django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002\test_calendar>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK
Go back to default project folder. Now you can test using this command:
(django_test_002-bp-hUvnN) D:\Projects\Python\django_test_002\test_calendar>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
June 13, 2020 - 21:52:42
Django version 3.0.7, using settings 'test_calendar.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
You will see a simple word: hello. Let's fix the admin login by adding user:
python manage.py createsuperuser
Username (leave blank to use 'catal'): catafest
Email address: catafest@yahoo.com
Password:
I set user catafest and password admin76 and then use the next command to see the result on http://127.0.0.1:8000/admin:
python manage.py runserver
The next step is to create a Event class into models.py file from first_calendar:
from django.db import models

class Event(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
Then add this class into admin.py file:
from django.contrib import admin
from first_calendar.models import Event

admin.site.register(Event)
This tutorial set the one default Django project with the Django framework version 3.0.7 .

Sunday, June 7, 2020

Python 3.8.3 : Using the fabric python module - part 002.

This is second tutorial about the fabric.
Using the old example, I will show you how can use it with some basic features.
The example cover these issues:
  • show fabric version;
  • use task decorator;
  • import and use multiple hosts;
The documentation page come with this info about task:
Fabric 1.1 introduced the Task class to facilitate new features and enable some programming best practices, specifically:
  Object-oriented tasks. Inheritance and all that comes with it can make for much more sensible code reuse than passing around simple function objects. The classic style of task declaration didn’t entirely rule this out, but it also didn’t make it terribly easy.
  Namespaces. Having an explicit method of declaring tasks makes it easier to set up recursive namespaces without e.g. polluting your task list with the contents of Python’s os module (which would show up as valid “tasks” under the classic methodology.)
With the introduction of Task, there are two ways to set up new tasks:
 Decorate a regular module level function with @task, which transparently wraps the function in a Task subclass. The function name will be used as the task name when invoking.
 Subclass Task (Task itself is intended to be abstract), define a run method, and instantiate your subclass at module level. Instances’ name attributes are used as the task name; if omitted the instance’s variable name will be used instead.
Let's see the example:
import fabric
from fabric import Connection
print("fabric.__version__")
print(fabric.__version__)

print("fabric.__version_info__")
print(fabric.__version_info__)

print("dir(fabric)")
print(dir(fabric))

import getpass
host = "catafest@tty.sdf.org"
password = getpass.getpass('Password for SDF account:')
with Connection("catafest@tty.sdf.org", connect_kwargs={"password":password}) as con:
    print("I will run command: ls")
    con.run("ls")
    
# using the task decorator 
from fabric import task
@task    
def processes(con):
    return con.run("ps -aux", hide = True).stdout.strip()

# print processes
print(processes(con))
con.run("exit")
# use the import for multiple host with all modules

from fabric import Connection, Config, SerialGroup, ThreadingGroup, exceptions, runners
from fabric.exceptions import GroupException

hosts = "catafest@tty.sdf.org,catafest@tty.sdf.org"

def testHosts(hosts):
    # Get list of hosts from somewhere, and convert them to connections
    hosts = hosts.split(",")
    servers = [Connection(host=host,connect_kwargs={"password":password}) for host in hosts]
    thread_group = ThreadingGroup.from_connections(servers)
    results = thread_group.run("who -a", hide=True)
    for r in results:
        connection = results[r]
        return connection.stdout.strip() 
        
print(testHosts(hosts))
The result of this python script:
fabric.__version__
2.5.0
fabric.__version_info__
(2, 5, 0)
dir(fabric)
['Config', 'Connection', 'Executor', 'Group', 'GroupResult', 'Remote', 'Result', 'SerialGroup', 'Task', 
'ThreadingGroup', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', 
'__package__', '__path__', '__spec__', '__version__', '__version_info__', '_version', 'config', 'connection', 
'exceptions', 'executor', 'group', 'runners', 'task', 'tasks', 'transfer', 'tunnels', 'util']
Password for SDF account:
I will run command: ls
USER            PID %CPU %MEM    VSZ    RSS TTY     STAT STARTED     TIME COMMAND
...
catafest      10431  0.0  0.0  30496   3120 ?       S     5:50PM  0:00.00 sshd:
...
catafest      19243  0.0  0.0  12008   1096 ?       O     5:50PM  0:00.00 ps -a
...
user   pts/0    Jun  7 17:40 00:10         0  term=0 exit=0 sess=0 type=user process  ...