<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="https://wiki.paskvil.com/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://wiki.paskvil.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Admin</id>
		<title>PaskvilWiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.paskvil.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Admin"/>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Special:Contributions/Admin"/>
		<updated>2026-04-10T04:03:26Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.22.0</generator>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_PSQL</id>
		<title>Short Notes on PSQL</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_PSQL"/>
				<updated>2021-09-17T10:50:05Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Set Sequence Value to Max of Table's ID */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;PSQL aka Postgres aka PostgreSQL... I prefer psql.&lt;br /&gt;
&lt;br /&gt;
== Dump and Restore ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;dump:&lt;br /&gt;
$ pg_dump -h host -p 5432 -U user -F c -b -v -f /tmp/db_name.backup db_name&lt;br /&gt;
restore:&lt;br /&gt;
$ pg_restore -h host -p 5432 -U user -d db_name -v /tmp/db_name.backup&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Delete Duplicate Lines ==&lt;br /&gt;
&lt;br /&gt;
Before you can add a &amp;lt;tt&amp;gt;unique&amp;lt;/tt&amp;gt; constraint to a table, you have to make sure it does satisfy this criteria.&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;table_T&amp;lt;/tt&amp;gt; and columns &amp;lt;tt&amp;gt;criteria_1&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;criteria_N&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;;&lt;br /&gt;
;; list rows that do not satisfy the uniqueness constraint&lt;br /&gt;
;;&lt;br /&gt;
SELECT&lt;br /&gt;
    criteria_1,&lt;br /&gt;
    ...&lt;br /&gt;
    criteria_N,&lt;br /&gt;
    COUNT(*)&lt;br /&gt;
FROM&lt;br /&gt;
    table_T&lt;br /&gt;
GROUP BY&lt;br /&gt;
    criteria_1, ..., criteria_N&lt;br /&gt;
HAVING&lt;br /&gt;
    COUNT(*) &amp;gt; 1&lt;br /&gt;
ORDER BY&lt;br /&gt;
    criteria_1, ..., criteria_N;&lt;br /&gt;
&lt;br /&gt;
;;&lt;br /&gt;
;; delete all rows that do not satisfy the constraint, keeping the ones with lowest id value&lt;br /&gt;
;;&lt;br /&gt;
DELETE  FROM&lt;br /&gt;
    table_T a&lt;br /&gt;
        USING table_T b&lt;br /&gt;
WHERE&lt;br /&gt;
    a.id &amp;gt; b.id&lt;br /&gt;
    AND a.criteria_1 = b.criteria_1&lt;br /&gt;
    ...&lt;br /&gt;
    AND a.criteria_N = b.criteria_N;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set Sequence Value to Max of Table's ID ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT setval('table_id_seq', (SELECT MAX(id) FROM table));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Find and Kill Stuck Queries ==&lt;br /&gt;
&lt;br /&gt;
To get list of queries that are running for more than 5 minutes:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT                          &lt;br /&gt;
  pid,&lt;br /&gt;
  NOW() - pg_stat_activity.query_start AS duration,&lt;br /&gt;
  query,&lt;br /&gt;
  state&lt;br /&gt;
FROM pg_stat_activity&lt;br /&gt;
WHERE (NOW() - pg_stat_activity.query_start) &amp;gt; INTERVAL '5 MINUTES';&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kill these by PID:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT pg_terminate_backend(_pid_);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2021-09-15T16:09:56Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Subqueries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Miscellaneous ==&lt;br /&gt;
&lt;br /&gt;
=== Date, Time, Datetime ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;d: datetime.date = ...&lt;br /&gt;
t: datetime.time = ...&lt;br /&gt;
dt: datetime.datetime = ...&lt;br /&gt;
&lt;br /&gt;
dt.date() -&amp;gt; datetime.date&lt;br /&gt;
dt.time() -&amp;gt; datetime.time&lt;br /&gt;
datetime.datetime.combine(d, t) -&amp;gt; datetime.datetime&lt;br /&gt;
in particular: datetime.datetime.combine(d, datetime.time(0, 0, 0)) -&amp;gt; start of date `d` as datetime&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;strftime()&amp;lt;/tt&amp;gt; Formatting ===&lt;br /&gt;
&lt;br /&gt;
Examples for ''Thu Dec 3, 2020, 01:23:45.678'' - &amp;lt;tt&amp;gt;datetime.datetime(2020, 12, 3, 1, 23, 45, 678000)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%y       - year (20)&lt;br /&gt;
%Y       - year (2020)&lt;br /&gt;
%m / %-m - month zero-/un- padded (12 / 12)&lt;br /&gt;
%d / %-d - day zero-/un- padded (03 / 3)&lt;br /&gt;
%H / %-H - hour zero-/un- padded, 24-hour clock (01 / 1)&lt;br /&gt;
%I / %-I - hour zero-/un- padded, 12-hour clock (01 / 1)&lt;br /&gt;
%p       - time of day (AM)&lt;br /&gt;
%M / %-M - minute zero-/un- padded (23 / 23)&lt;br /&gt;
%S / %-S - second zero-/un- padded (45 / 45)&lt;br /&gt;
%f       - microsecond (678000)&lt;br /&gt;
%z       - timezone as +HHMM or -HHMM, empty if object is naive&lt;br /&gt;
%Z       - timezone name, empty if object is naive&lt;br /&gt;
%j / %-j - day of year zero-/un- padded (338 / 338)&lt;br /&gt;
%a / %A  - weekday name, abb. / full (Thu / Thursday)&lt;br /&gt;
%w       - weekday as decimal, 0-Sunday, 6-Saturday (4)&lt;br /&gt;
%U / %W  - week number, week starting on Sunday / Monday (48 / 48)&lt;br /&gt;
%b / %B  - month name, abb. / full (Dec / December)&lt;br /&gt;
%c       - locale appropriate date and time representation (Thu Dec  3 01:23:45 2020)&lt;br /&gt;
%x       - locale appropriate date representation (12/03/20)&lt;br /&gt;
%X       - locale appropriate time representation (01:23:45)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Select, Where, Group ===&lt;br /&gt;
&lt;br /&gt;
=== Updating ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
session.query(Table).\&lt;br /&gt;
    filter(Table.id.in_(...)).\&lt;br /&gt;
    update({&lt;br /&gt;
        Table.column1: 10,&lt;br /&gt;
        Table.column2: Table.column2 + 50&lt;br /&gt;
    })&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scalar Values ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;min&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;max&amp;lt;/tt&amp;gt;, ... ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from sqlalchemy import func&lt;br /&gt;
&lt;br /&gt;
max_value = session.query(sqlalchemy.func.max(Table.column)).scalar()&lt;br /&gt;
&lt;br /&gt;
# or, for multiple, just use&lt;br /&gt;
session.query(sqlalchemy.func.min(Table.column), sqlalchemy.func.max(Table.column)).first()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model, including Indexes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable, CreateIndex&lt;br /&gt;
from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
def print_create_statement(model):&lt;br /&gt;
    print(CreateTable(model.__table__).compile(dialect=postgresql.dialect()))&lt;br /&gt;
    for index in model.__table__.indexes:&lt;br /&gt;
        print(CreateIndex(index).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Aliases ===&lt;br /&gt;
&lt;br /&gt;
Aliases are super useful when you e.g. need to select something twice.&lt;br /&gt;
&lt;br /&gt;
For instance, having &amp;quot;Book&amp;quot; records that have &amp;quot;author&amp;quot; and &amp;quot;editor&amp;quot; columns pointing to &amp;quot;User&amp;quot; table:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from sqlalchemy.orm import aliased&lt;br /&gt;
&lt;br /&gt;
author = aliased(User)&lt;br /&gt;
editor = aliased(User)&lt;br /&gt;
book_data = session.query(Book, author.name, editor.name).\&lt;br /&gt;
    select_from(Book).\&lt;br /&gt;
    join(author, Book.author_id == author.id).\&lt;br /&gt;
    join(editor, Book.editor_id == editor.id).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== iPython fails with ''NameError: name 'sys' is not defined'' on autocompletion ==&lt;br /&gt;
&lt;br /&gt;
This is due to new version of &amp;lt;tt&amp;gt;jedi&amp;lt;/tt&amp;gt; module not being compatible with iPython.&lt;br /&gt;
&lt;br /&gt;
Just downgrade it to pre-0.18 version, using&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install --upgrade 'jedi&amp;lt;0.18.0'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2021-07-09T15:34:24Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* PSQL, Postgres, PostgreSQL */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&lt;br /&gt;
$ jul () { date -d &amp;quot;$1-01-01 +$2 days -1 day&amp;quot; &amp;quot;+%Y%m%d&amp;quot;; }   - `jul $year $daynum` prints $daynum's day of $year, with Jan 1st being day 1&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
* ''convert album contained in APE or similar file with CUE into separate MP3 tracks''&lt;br /&gt;
 ffmpeg -i cd.ape -ab 256k cd.mp3&lt;br /&gt;
 mp3splt -a -c cd.cue cd.mp3&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on JS|All things JS - React, Vue, ...]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
* Shrink ''ibfile1'' InnoDB File&lt;br /&gt;
* Index JSON columns&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PSQL|PSQL, Postgres, PostgreSQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Dump and Restore&lt;br /&gt;
* Delete Duplicate Rows&lt;br /&gt;
* Set Sequence Value to Max of Table's ID&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
* iPython fails with ''NameError: name 'sys' is not defined'' on autocompletion&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7 python3.7-venv&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
'''update''' - available as a ''snap'' as well, no need to add ''apt'' sources - https://node.dev/node-binary&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_PSQL</id>
		<title>Short Notes on PSQL</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_PSQL"/>
				<updated>2021-07-09T15:33:50Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;PSQL aka Postgres aka PostgreSQL... I prefer psql.&lt;br /&gt;
&lt;br /&gt;
== Dump and Restore ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;dump:&lt;br /&gt;
$ pg_dump -h host -p 5432 -U user -F c -b -v -f /tmp/db_name.backup db_name&lt;br /&gt;
restore:&lt;br /&gt;
$ pg_restore -h host -p 5432 -U user -d db_name -v /tmp/db_name.backup&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Delete Duplicate Lines ==&lt;br /&gt;
&lt;br /&gt;
Before you can add a &amp;lt;tt&amp;gt;unique&amp;lt;/tt&amp;gt; constraint to a table, you have to make sure it does satisfy this criteria.&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;table_T&amp;lt;/tt&amp;gt; and columns &amp;lt;tt&amp;gt;criteria_1&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;criteria_N&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;;&lt;br /&gt;
;; list rows that do not satisfy the uniqueness constraint&lt;br /&gt;
;;&lt;br /&gt;
SELECT&lt;br /&gt;
    criteria_1,&lt;br /&gt;
    ...&lt;br /&gt;
    criteria_N,&lt;br /&gt;
    COUNT(*)&lt;br /&gt;
FROM&lt;br /&gt;
    table_T&lt;br /&gt;
GROUP BY&lt;br /&gt;
    criteria_1, ..., criteria_N&lt;br /&gt;
HAVING&lt;br /&gt;
    COUNT(*) &amp;gt; 1&lt;br /&gt;
ORDER BY&lt;br /&gt;
    criteria_1, ..., criteria_N;&lt;br /&gt;
&lt;br /&gt;
;;&lt;br /&gt;
;; delete all rows that do not satisfy the constraint, keeping the ones with lowest id value&lt;br /&gt;
;;&lt;br /&gt;
DELETE  FROM&lt;br /&gt;
    table_T a&lt;br /&gt;
        USING table_T b&lt;br /&gt;
WHERE&lt;br /&gt;
    a.id &amp;gt; b.id&lt;br /&gt;
    AND a.criteria_1 = b.criteria_1&lt;br /&gt;
    ...&lt;br /&gt;
    AND a.criteria_N = b.criteria_N;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set Sequence Value to Max of Table's ID ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT setval('table_id_seq', (SELECT MAX(id) FROM table));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2021-05-17T15:15:03Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Python */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&lt;br /&gt;
$ jul () { date -d &amp;quot;$1-01-01 +$2 days -1 day&amp;quot; &amp;quot;+%Y%m%d&amp;quot;; }   - `jul $year $daynum` prints $daynum's day of $year, with Jan 1st being day 1&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
* ''convert album contained in APE or similar file with CUE into separate MP3 tracks''&lt;br /&gt;
 ffmpeg -i cd.ape -ab 256k cd.mp3&lt;br /&gt;
 mp3splt -a -c cd.cue cd.mp3&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on JS|All things JS - React, Vue, ...]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
* Shrink ''ibfile1'' InnoDB File&lt;br /&gt;
* Index JSON columns&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PSQL|PSQL, Postgres, PostgreSQL]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
* iPython fails with ''NameError: name 'sys' is not defined'' on autocompletion&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7 python3.7-venv&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
'''update''' - available as a ''snap'' as well, no need to add ''apt'' sources - https://node.dev/node-binary&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2021-05-17T15:14:50Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* iPython fails with NameError: name 'sys' is not defined on autocompletion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Miscellaneous ==&lt;br /&gt;
&lt;br /&gt;
=== Date, Time, Datetime ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;d: datetime.date = ...&lt;br /&gt;
t: datetime.time = ...&lt;br /&gt;
dt: datetime.datetime = ...&lt;br /&gt;
&lt;br /&gt;
dt.date() -&amp;gt; datetime.date&lt;br /&gt;
dt.time() -&amp;gt; datetime.time&lt;br /&gt;
datetime.datetime.combine(d, t) -&amp;gt; datetime.datetime&lt;br /&gt;
in particular: datetime.datetime.combine(d, datetime.time(0, 0, 0)) -&amp;gt; start of date `d` as datetime&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;strftime()&amp;lt;/tt&amp;gt; Formatting ===&lt;br /&gt;
&lt;br /&gt;
Examples for ''Thu Dec 3, 2020, 01:23:45.678'' - &amp;lt;tt&amp;gt;datetime.datetime(2020, 12, 3, 1, 23, 45, 678000)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%y       - year (20)&lt;br /&gt;
%Y       - year (2020)&lt;br /&gt;
%m / %-m - month zero-/un- padded (12 / 12)&lt;br /&gt;
%d / %-d - day zero-/un- padded (03 / 3)&lt;br /&gt;
%H / %-H - hour zero-/un- padded, 24-hour clock (01 / 1)&lt;br /&gt;
%I / %-I - hour zero-/un- padded, 12-hour clock (01 / 1)&lt;br /&gt;
%p       - time of day (AM)&lt;br /&gt;
%M / %-M - minute zero-/un- padded (23 / 23)&lt;br /&gt;
%S / %-S - second zero-/un- padded (45 / 45)&lt;br /&gt;
%f       - microsecond (678000)&lt;br /&gt;
%z       - timezone as +HHMM or -HHMM, empty if object is naive&lt;br /&gt;
%Z       - timezone name, empty if object is naive&lt;br /&gt;
%j / %-j - day of year zero-/un- padded (338 / 338)&lt;br /&gt;
%a / %A  - weekday name, abb. / full (Thu / Thursday)&lt;br /&gt;
%w       - weekday as decimal, 0-Sunday, 6-Saturday (4)&lt;br /&gt;
%U / %W  - week number, week starting on Sunday / Monday (48 / 48)&lt;br /&gt;
%b / %B  - month name, abb. / full (Dec / December)&lt;br /&gt;
%c       - locale appropriate date and time representation (Thu Dec  3 01:23:45 2020)&lt;br /&gt;
%x       - locale appropriate date representation (12/03/20)&lt;br /&gt;
%X       - locale appropriate time representation (01:23:45)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Select, Where, Group ===&lt;br /&gt;
&lt;br /&gt;
=== Updating ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
session.query(Table).\&lt;br /&gt;
    filter(Table.id.in_(...)).\&lt;br /&gt;
    update({&lt;br /&gt;
        Table.column1: 10,&lt;br /&gt;
        Table.column2: Table.column2 + 50&lt;br /&gt;
    })&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scalar Values ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;min&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;max&amp;lt;/tt&amp;gt;, ... ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from sqlalchemy import func&lt;br /&gt;
&lt;br /&gt;
max_value = session.query(sqlalchemy.func.max(Table.column)).scalar()&lt;br /&gt;
&lt;br /&gt;
# or, for multiple, just use&lt;br /&gt;
session.query(sqlalchemy.func.min(Table.column), sqlalchemy.func.max(Table.column)).first()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model, including Indexes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable, CreateIndex&lt;br /&gt;
from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
def print_create_statement(model):&lt;br /&gt;
    print(CreateTable(model.__table__).compile(dialect=postgresql.dialect()))&lt;br /&gt;
    for index in model.__table__.indexes:&lt;br /&gt;
        print(CreateIndex(index).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== iPython fails with ''NameError: name 'sys' is not defined'' on autocompletion ==&lt;br /&gt;
&lt;br /&gt;
This is due to new version of &amp;lt;tt&amp;gt;jedi&amp;lt;/tt&amp;gt; module not being compatible with iPython.&lt;br /&gt;
&lt;br /&gt;
Just downgrade it to pre-0.18 version, using&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install --upgrade 'jedi&amp;lt;0.18.0'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2021-05-17T15:14:18Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Miscellaneous ==&lt;br /&gt;
&lt;br /&gt;
=== Date, Time, Datetime ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;d: datetime.date = ...&lt;br /&gt;
t: datetime.time = ...&lt;br /&gt;
dt: datetime.datetime = ...&lt;br /&gt;
&lt;br /&gt;
dt.date() -&amp;gt; datetime.date&lt;br /&gt;
dt.time() -&amp;gt; datetime.time&lt;br /&gt;
datetime.datetime.combine(d, t) -&amp;gt; datetime.datetime&lt;br /&gt;
in particular: datetime.datetime.combine(d, datetime.time(0, 0, 0)) -&amp;gt; start of date `d` as datetime&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;strftime()&amp;lt;/tt&amp;gt; Formatting ===&lt;br /&gt;
&lt;br /&gt;
Examples for ''Thu Dec 3, 2020, 01:23:45.678'' - &amp;lt;tt&amp;gt;datetime.datetime(2020, 12, 3, 1, 23, 45, 678000)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%y       - year (20)&lt;br /&gt;
%Y       - year (2020)&lt;br /&gt;
%m / %-m - month zero-/un- padded (12 / 12)&lt;br /&gt;
%d / %-d - day zero-/un- padded (03 / 3)&lt;br /&gt;
%H / %-H - hour zero-/un- padded, 24-hour clock (01 / 1)&lt;br /&gt;
%I / %-I - hour zero-/un- padded, 12-hour clock (01 / 1)&lt;br /&gt;
%p       - time of day (AM)&lt;br /&gt;
%M / %-M - minute zero-/un- padded (23 / 23)&lt;br /&gt;
%S / %-S - second zero-/un- padded (45 / 45)&lt;br /&gt;
%f       - microsecond (678000)&lt;br /&gt;
%z       - timezone as +HHMM or -HHMM, empty if object is naive&lt;br /&gt;
%Z       - timezone name, empty if object is naive&lt;br /&gt;
%j / %-j - day of year zero-/un- padded (338 / 338)&lt;br /&gt;
%a / %A  - weekday name, abb. / full (Thu / Thursday)&lt;br /&gt;
%w       - weekday as decimal, 0-Sunday, 6-Saturday (4)&lt;br /&gt;
%U / %W  - week number, week starting on Sunday / Monday (48 / 48)&lt;br /&gt;
%b / %B  - month name, abb. / full (Dec / December)&lt;br /&gt;
%c       - locale appropriate date and time representation (Thu Dec  3 01:23:45 2020)&lt;br /&gt;
%x       - locale appropriate date representation (12/03/20)&lt;br /&gt;
%X       - locale appropriate time representation (01:23:45)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Select, Where, Group ===&lt;br /&gt;
&lt;br /&gt;
=== Updating ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
session.query(Table).\&lt;br /&gt;
    filter(Table.id.in_(...)).\&lt;br /&gt;
    update({&lt;br /&gt;
        Table.column1: 10,&lt;br /&gt;
        Table.column2: Table.column2 + 50&lt;br /&gt;
    })&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scalar Values ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;min&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;max&amp;lt;/tt&amp;gt;, ... ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from sqlalchemy import func&lt;br /&gt;
&lt;br /&gt;
max_value = session.query(sqlalchemy.func.max(Table.column)).scalar()&lt;br /&gt;
&lt;br /&gt;
# or, for multiple, just use&lt;br /&gt;
session.query(sqlalchemy.func.min(Table.column), sqlalchemy.func.max(Table.column)).first()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model, including Indexes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable, CreateIndex&lt;br /&gt;
from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
def print_create_statement(model):&lt;br /&gt;
    print(CreateTable(model.__table__).compile(dialect=postgresql.dialect()))&lt;br /&gt;
    for index in model.__table__.indexes:&lt;br /&gt;
        print(CreateIndex(index).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== iPython fails with &amp;lt;tt&amp;gt;NameError: name 'sys' is not defined&amp;lt;/tt&amp;gt; on autocompletion ==&lt;br /&gt;
&lt;br /&gt;
This is due to new version of &amp;lt;tt&amp;gt;jedi&amp;lt;/tt&amp;gt; module not being compatible with iPython.&lt;br /&gt;
&lt;br /&gt;
Just downgrade it to pre-0.18 version, using&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install --upgrade 'jedi&amp;lt;0.18.0'&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_MySQL</id>
		<title>Short Notes on MySQL</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_MySQL"/>
				<updated>2021-04-23T01:01:52Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Error 1045: Access denied ==&lt;br /&gt;
&lt;br /&gt;
The 1045 bug may appear under many circumstances, and it may be related to multiple problems.&lt;br /&gt;
&lt;br /&gt;
Kind of &amp;quot;legacy&amp;quot; problem might be that there is anonymous user defined. Such user will show up with empty ''Name'' in the following set:&lt;br /&gt;
&amp;lt;pre&amp;gt;mysql&amp;gt; select User, Host, Password from mysql.user;&lt;br /&gt;
+-------------+----------------+-------------------------------------------+&lt;br /&gt;
| User        | Host           | Password                                  |&lt;br /&gt;
+-------------+----------------+-------------------------------------------+&lt;br /&gt;
| root        | localhost      | [.................hash..................] |&lt;br /&gt;
| root        | 127.0.0.1      | [.................hash..................] |&lt;br /&gt;
|             | %              | [.................hash..................] |&lt;br /&gt;
| ...                                                                      |&lt;br /&gt;
+-------------+----------------+-------------------------------------------+&amp;lt;/pre&amp;gt;&lt;br /&gt;
This user will be selected first, and will interfere with your login. Removing such user is generally a good idea anyways.&lt;br /&gt;
&lt;br /&gt;
Next problem, when connecting remotely, may be caused simply by networking being disabled, or that MySQL binds only to local IP.&lt;br /&gt;
&amp;lt;pre&amp;gt;show variables like 'skip_networking';&lt;br /&gt;
+-----------------+-------+&lt;br /&gt;
| Variable_name   | Value |&lt;br /&gt;
+-----------------+-------+&lt;br /&gt;
| skip_networking | ON    |&lt;br /&gt;
+-----------------+-------+&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can either set this variable to &amp;lt;tt&amp;gt;OFF&amp;lt;/tt&amp;gt;, or comment out the setting in ''/etc/mysql/my.cnf'':&lt;br /&gt;
&amp;lt;pre&amp;gt;# skip-networking&amp;lt;/pre&amp;gt;&lt;br /&gt;
One more option is that your MySQL server binds only to local IP; under &amp;lt;tt&amp;gt;[mysqld]&amp;lt;/tt&amp;gt; section in ''/etc/mysql/my.cnf'' comment out bind setting, or replace it with your public IP:&lt;br /&gt;
&amp;lt;pre&amp;gt;# bind-address = 127.0.0.1&lt;br /&gt;
# or&lt;br /&gt;
bind-address = 123.1.2.3&amp;lt;/pre&amp;gt;&lt;br /&gt;
If none of this helps, you're left with user privileges. Make sure the user that is trying to connect is at all present in system:&lt;br /&gt;
&amp;lt;pre&amp;gt;mysql&amp;gt; select User, Host, Password from mysql.user;&lt;br /&gt;
+-------------+----------------+-------------------------------------------+&lt;br /&gt;
| User        | Host           | Password                                  |&lt;br /&gt;
+-------------+----------------+-------------------------------------------+&lt;br /&gt;
| ...                                                                      |&lt;br /&gt;
+-------------+----------------+-------------------------------------------+&amp;lt;/pre&amp;gt;&lt;br /&gt;
If it is (make sure both ''User'' and ''Host'' match, or ''Host'' is &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;), make sure it has rights granted:&lt;br /&gt;
&amp;lt;pre&amp;gt;show grants for 'dbuser'@'example.com';&amp;lt;/pre&amp;gt;&lt;br /&gt;
If the user does not exist, or if it doesn't have rights granted, you can create and/or update it at once with:&lt;br /&gt;
&amp;lt;pre&amp;gt;grant all on db.* to 'dbuser'@'example.com' identified by 'password';&amp;lt;/pre&amp;gt;&lt;br /&gt;
Of course, restrict the ''grant all'' to just rights required whenever possible.&lt;br /&gt;
&lt;br /&gt;
Also, make sure to include the &amp;lt;tt&amp;gt;identified by 'password'&amp;lt;/tt&amp;gt; each time, otherwise, if the user does not exist in system, it'll be left with empty password.&lt;br /&gt;
&lt;br /&gt;
One last thing - make sure individual users with the same username have the same password (if this is desirable):&lt;br /&gt;
&amp;lt;pre&amp;gt;mysql&amp;gt; select User, Host, Password from mysql.user where User = 'dbuser';&lt;br /&gt;
+-------------+----------------+-------------------------------------------+&lt;br /&gt;
| User        | Host           | Password                                  |&lt;br /&gt;
+-------------+----------------+-------------------------------------------+&lt;br /&gt;
| dbuser      | localhost      | [.................hash..................] |&lt;br /&gt;
| dbuser      | 127.0.0.1      | [.................hash..................] |&lt;br /&gt;
| dbuser      | example.com    |                                           |&lt;br /&gt;
+-------------+----------------+-------------------------------------------+&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that &amp;lt;tt&amp;gt;'dbuser'@'example.com'&amp;lt;/tt&amp;gt; has empty password! It's just as possible that the hashes/passwords differ. To fix this, use&lt;br /&gt;
&amp;lt;pre&amp;gt;set password for 'dbuser'@'example.com' = PASSWORD('password');&amp;lt;/pre&amp;gt;&lt;br /&gt;
After all this, you should be able to connect... hopefully.&lt;br /&gt;
&lt;br /&gt;
'''Note''': You can also&lt;br /&gt;
&amp;lt;pre&amp;gt;flush privileges;&amp;lt;/pre&amp;gt;&lt;br /&gt;
after updates to the user grants and passwords, but this is rarely necessary unless you're on a MySQL Cluster.&lt;br /&gt;
&lt;br /&gt;
== The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall ==&lt;br /&gt;
&lt;br /&gt;
Some time back I had a problem - gaps in values in &amp;lt;tt&amp;gt;auto_increment&amp;lt;/tt&amp;gt; column in MySQL table.&lt;br /&gt;
&lt;br /&gt;
It turns out that when using &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt;, the &amp;lt;tt&amp;gt;auto_increment&amp;lt;/tt&amp;gt; counter is being incremented even if the row exists, and is only being updated.&lt;br /&gt;
&lt;br /&gt;
If you want the &amp;lt;tt&amp;gt;auto_increment&amp;lt;/tt&amp;gt; column to be contiguous, or simply don't wanna waste values available, you'll have to check if the row exists and use &amp;lt;tt&amp;gt;insert&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;update&amp;lt;/tt&amp;gt; accordingly.&lt;br /&gt;
&lt;br /&gt;
This might especially become a problem in tables where updates to rows are much more frequent than inserts, and you might run out of values for the ID column.&lt;br /&gt;
&lt;br /&gt;
== Shrink ''ibfile1'' InnoDB File ==&lt;br /&gt;
&lt;br /&gt;
'''Warning''' - it's not easily possible :)&lt;br /&gt;
&lt;br /&gt;
That said, here are steps to get rid of the problem, to certain extent:&lt;br /&gt;
* it's better to activate &amp;lt;tt&amp;gt;innodb_file_per_table&amp;lt;/tt&amp;gt; setting in ''/etc/mysql/my.cnf'', under &amp;lt;tt&amp;gt;[mysqld]&amp;lt;/tt&amp;gt; section,&lt;br /&gt;
** this won't solve the problem of growing files, but each table will be in separate file, and dropping a table will result in file being deleted,&lt;br /&gt;
* if you already have existing data in MySQL, do the following (you can ignore ''information_schema'' database in the process):&lt;br /&gt;
** &amp;lt;tt&amp;gt;mysqldump&amp;lt;/tt&amp;gt; all databases, procedures, triggers, etc. except ''mysql'' and ''performance_schema'' databases,&lt;br /&gt;
** drop all databases except ''mysql'' and ''performance_schema'',&lt;br /&gt;
** stop ''mysql'' service,&lt;br /&gt;
** delete the ''ibdata1'' and ''ib_log*'' files in MySQL data folder,&lt;br /&gt;
** start ''mysql'' service,&lt;br /&gt;
** restore databases from dump.&lt;br /&gt;
&lt;br /&gt;
== Index JSON columns ==&lt;br /&gt;
&lt;br /&gt;
MySQL does not support direct indexing of JSON columns, or values within.&lt;br /&gt;
&lt;br /&gt;
That said, it does support ''generated'' columns based on data within.&lt;br /&gt;
&lt;br /&gt;
Consider book storage, where we want to index ''title'' and ''author'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
'data' column of 'book' table contains:&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;title&amp;quot;: &amp;quot;...&amp;quot;,&lt;br /&gt;
  &amp;quot;author&amp;quot;: &amp;quot;...&amp;quot;,&lt;br /&gt;
  ... other fields ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To alter the &amp;lt;tt&amp;gt;book&amp;lt;/tt&amp;gt; table, you need to add 2 generated columns, e.g. to type &amp;lt;tt&amp;gt;VARCHAR(255)&amp;lt;/tt&amp;gt;, and index these in the usual fashion:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE book&lt;br /&gt;
ADD data_title VARCHAR(255) GENERATED ALWAYS AS (data -&amp;gt;&amp;gt; '$.title') VIRTUAL,&lt;br /&gt;
ADD data_author VARCHAR(255) GENERATED ALWAYS AS (data -&amp;gt;&amp;gt; '$.author') VIRTUAL;&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE book&lt;br /&gt;
ADD INDEX (data_title),&lt;br /&gt;
ADD INDEX (data_author);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Note'': MySQL, unlike SQL standard, allows multiple &amp;lt;tt&amp;gt;ALTER TABLE&amp;lt;/tt&amp;gt; actions within single query, simply comma separated.&lt;br /&gt;
&lt;br /&gt;
''Note'': The &amp;lt;tt&amp;gt;GENERATED ALWAYS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;VIRTUAL&amp;lt;/tt&amp;gt; statements are not required, but I find it more explicit about your intentions.&lt;br /&gt;
The &amp;lt;tt&amp;gt;AS&amp;lt;/tt&amp;gt; automatically means that the column is generated based on other data, and generated columns are by default &amp;lt;tt&amp;gt;VIRTUAL&amp;lt;/tt&amp;gt; (the opposite is &amp;lt;tt&amp;gt;STORED&amp;lt;/tt&amp;gt;, which actually creates a column within table that is used for the data).&lt;br /&gt;
&lt;br /&gt;
''Note'': In most cases, MySQL's query planner is smart enough to use the generated column's index to execute queries involving the fields, thus you do not have to worry about using these columns, or whether your ORM is aware of generated columns :)&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2021-04-23T00:49:51Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* MySQL */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&lt;br /&gt;
$ jul () { date -d &amp;quot;$1-01-01 +$2 days -1 day&amp;quot; &amp;quot;+%Y%m%d&amp;quot;; }   - `jul $year $daynum` prints $daynum's day of $year, with Jan 1st being day 1&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
* ''convert album contained in APE or similar file with CUE into separate MP3 tracks''&lt;br /&gt;
 ffmpeg -i cd.ape -ab 256k cd.mp3&lt;br /&gt;
 mp3splt -a -c cd.cue cd.mp3&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on JS|All things JS - React, Vue, ...]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
* Shrink ''ibfile1'' InnoDB File&lt;br /&gt;
* Index JSON columns&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PSQL|PSQL, Postgres, PostgreSQL]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7 python3.7-venv&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
'''update''' - available as a ''snap'' as well, no need to add ''apt'' sources - https://node.dev/node-binary&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_git</id>
		<title>Short Notes on git</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_git"/>
				<updated>2021-03-20T01:58:46Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Basic Commands ==&lt;br /&gt;
&lt;br /&gt;
The ''git'' has 3 &amp;quot;trees&amp;quot; maintained automatically within your local repo - &amp;quot;working copy&amp;quot; is the files you're actually working on, &amp;quot;index&amp;quot; is kind of staging area, and &amp;quot;head&amp;quot; is your last actual commit.&lt;br /&gt;
You're working on your ''working copy'', then add changes to the ''index'', then push those to ''head'' locally, and finally push those to (remote) repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# two ways to check out a repo; 1) first local, then connect&lt;br /&gt;
$ git init                                   # init local copy&lt;br /&gt;
$ git remote add origin &amp;lt;server&amp;gt;             # connect it to remote&lt;br /&gt;
# or, 2) checkout a remote repo straight away&lt;br /&gt;
$ git clone /path/to/repo                    # create working copy of local repo&lt;br /&gt;
$ git clone user@host:/path/to/repo          # create working copy of remote repo&lt;br /&gt;
&lt;br /&gt;
$ git status                                 # get info about local copy, incl. branch ID, changes, etc.&lt;br /&gt;
&lt;br /&gt;
$ git fetch                                  # download changes but do not integrate in the HEAD&lt;br /&gt;
$ git pull                                   # update the local copy to the latest revision&lt;br /&gt;
$ git pull &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # pull specific branch&lt;br /&gt;
$ git diff &amp;lt;source&amp;gt; &amp;lt;dest&amp;gt;                   # view differences between &amp;quot;source&amp;quot; and &amp;quot;dest&amp;quot; branches&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                         # merge changes from another branch (e.g. &amp;quot;origin/master&amp;quot;)&lt;br /&gt;
                                             # you should merge from remote (&amp;quot;origin&amp;quot;) as your local copy may differ&lt;br /&gt;
&lt;br /&gt;
# set meld as diff and merge tool; use --global to apply globally, not just per-repo&lt;br /&gt;
$ git config difftool meld&lt;br /&gt;
$ git config difftool.prompt false           # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool meld                  # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool.prompt false&lt;br /&gt;
$ git difftool                               # you need to use &amp;quot;difftool&amp;quot; to run meld for diff, not just `git diff`&lt;br /&gt;
$ git mergetool                              # run this only after `git merge` if there are any conflicts to be resolved&lt;br /&gt;
&lt;br /&gt;
# getting the changes to the remote repo&lt;br /&gt;
$ git add [-i] &amp;lt;file&amp;gt;                        # add changes from file(s) to index (-i = interactive)&lt;br /&gt;
$ git commit -m 'message'                    # commit changes from index to head&lt;br /&gt;
$ git push origin master                     # push changes from head to master branch, or&lt;br /&gt;
$ git push &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # push changes to &amp;lt;branch&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ git checkout -- &amp;lt;file&amp;gt;                     # revert file and replace with current HEAD version, exc. of changes added to Index&lt;br /&gt;
$ git fetch origin                           # fetch latest history from server&lt;br /&gt;
$ git reset --hard origin/master             # drop all local changes, incl. those in Index&lt;br /&gt;
&lt;br /&gt;
# branching&lt;br /&gt;
$ git branch -av                             # list existing branches&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                   # create a new branch, and switch to it, or&lt;br /&gt;
$ git checkout &amp;lt;branch&amp;gt;                      # switch to branch (make it your HEAD)&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt; --set-upstream    # make the branch available to others, and set the upstream&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                     # delete local branch&lt;br /&gt;
$ git branch -dr &amp;lt;remote/branch&amp;gt;             # delete remote branch&lt;br /&gt;
&lt;br /&gt;
# other stuff&lt;br /&gt;
$ git tag &amp;lt;tag name&amp;gt; &amp;lt;commit id&amp;gt;             # create tag from a commit&lt;br /&gt;
$ git log --pretty=oneline [--author=&amp;lt;name&amp;gt;] # one-line per commit listing&lt;br /&gt;
$ git log --graph --oneline --decorate --all # ascii tree of branches, tags, ...&lt;br /&gt;
$ git log --name-status                      # list changed files&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;svn:externals&amp;quot; like inclusion of another repo; need to commit this as well&lt;br /&gt;
$ git submodule add -b &amp;lt;branch&amp;gt; &amp;lt;repo&amp;gt; [&amp;lt;folder&amp;gt;]&lt;br /&gt;
$ git add &amp;lt;folder&amp;gt; .gitmodules ; + commit ; + push&lt;br /&gt;
&lt;br /&gt;
$ git submodule update --remote              # update the submodules from their respective repo's&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Typical Flow ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone [remote repo]                     # get a local copy of the repo&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                    # start a new branch&lt;br /&gt;
$ git push --set-upstream origin &amp;lt;branch&amp;gt;     # set remote as upstream, to be able to push to remote repo&lt;br /&gt;
&lt;br /&gt;
# do your changes...&lt;br /&gt;
$ git add &amp;lt;files&amp;gt;                             # register changes for commit&lt;br /&gt;
$ git commit -m 'message'&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt;                    # commit the branch with changes to repo&lt;br /&gt;
# repeat as needed...&lt;br /&gt;
&lt;br /&gt;
# once done with the branch&lt;br /&gt;
$ git merge master                            # pull all changes from &amp;quot;master&amp;quot;&lt;br /&gt;
$ git mergetool                               # resolve conflicts; commit again to branch if needed - `add`, `commit`, `push`&lt;br /&gt;
$ git checkout master                         # switch to master&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                          # this should pass ok; commit to &amp;quot;master&amp;quot; afterwards&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                      # clean up - remove the branch&lt;br /&gt;
$ git tag &amp;lt;tag&amp;gt; &amp;lt;commit id&amp;gt;                   # optionally, also tag the commit after merging&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resolve Conflict ===&lt;br /&gt;
&lt;br /&gt;
If on &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; you get a message:&lt;br /&gt;
&amp;lt;pre&amp;gt;error: Your local changes to the following files would be overwritten by merge:&lt;br /&gt;
	[list of files]&lt;br /&gt;
Please, commit your changes or stash them before you can merge.&lt;br /&gt;
Aborting&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to resolve the conflict manually.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git fetch&lt;br /&gt;
git add [file]&lt;br /&gt;
git commit -m 'resolving'&lt;br /&gt;
git merge&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At which point you'll get message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Auto-merging [files]&lt;br /&gt;
CONFLICT (content): Merge conflict in [files]&lt;br /&gt;
Automatic merge failed; fix conflicts and then commit the result.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you need to manually edit the file(s) to resolve the conflict, and then &amp;lt;tt&amp;gt;add/commit&amp;lt;/tt&amp;gt; the resolved file(s).&lt;br /&gt;
&lt;br /&gt;
== Small Tips ==&lt;br /&gt;
&lt;br /&gt;
=== Skip Retyping Your Password ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git config --global credential.helper store&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; and enter your username and password. These will be stored in &amp;lt;tt&amp;gt;~/.git-credentials&amp;lt;/tt&amp;gt; file and reused each time.&lt;br /&gt;
&lt;br /&gt;
=== Ignoring Files and Folders ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ touch .gitignore&lt;br /&gt;
# edit the file with your fave editor (folders should end with '/'):&lt;br /&gt;
folder/&lt;br /&gt;
file.txt&lt;br /&gt;
&lt;br /&gt;
# it's good practice to commit the file as well&lt;br /&gt;
$ git add .gitignore&lt;br /&gt;
$ git commit -m &amp;quot;Added .gitignore file&amp;quot;&lt;br /&gt;
$ git push origin master&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Current Branch ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git rev-parse --abbrev-ref HEAD&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can add this to &amp;lt;tt&amp;gt;.git/config&amp;lt;/tt&amp;gt; as alias:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;[alias]&lt;br /&gt;
current = rev-parse --abbrev-ref HEAD&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and then use it as&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git current&lt;br /&gt;
&amp;gt; master&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Set ''meld'' as your &amp;lt;tt&amp;gt;difftool&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mergetool&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Edit your &amp;lt;tt&amp;gt;~/.gitconfig&amp;lt;/tt&amp;gt; file as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;[diff]&lt;br /&gt;
    tool = meld&lt;br /&gt;
[difftool]&lt;br /&gt;
    prompt = false&lt;br /&gt;
[difftool &amp;quot;meld&amp;quot;]&lt;br /&gt;
    cmd = meld &amp;quot;$LOCAL&amp;quot; &amp;quot;$REMOTE&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, running &amp;lt;tt&amp;gt;git difftool&amp;lt;/tt&amp;gt; will bring up your dear ol' ''meld''.&lt;br /&gt;
&lt;br /&gt;
For resolution of merge conflicts, add to your &amp;lt;tt&amp;gt;~/.gitconfig&amp;lt;/tt&amp;gt; file, choosing one of the two options:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;[merge]&lt;br /&gt;
    tool = meld&lt;br /&gt;
[mergetool &amp;quot;meld&amp;quot;]&lt;br /&gt;
    # the middle file is the partially merged file, and you have to&lt;br /&gt;
    # make sense of the conflicting portions&lt;br /&gt;
    cmd = meld &amp;quot;$LOCAL&amp;quot; &amp;quot;$MERGED&amp;quot; &amp;quot;$REMOTE&amp;quot; --output &amp;quot;$MERGED&amp;quot;&lt;br /&gt;
    # the middle file is the &amp;quot;common ancestor&amp;quot; of the conflicting files,&lt;br /&gt;
    # and you have to choose bits and pieces to reconstruct the new merged file&lt;br /&gt;
    cmd = meld &amp;quot;$LOCAL&amp;quot; &amp;quot;$BASE&amp;quot; &amp;quot;$REMOTE&amp;quot; --output &amp;quot;$MERGED&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First option turns out better in case there was lots to merge, and just bit to resolve.&lt;br /&gt;
&lt;br /&gt;
The second option is better when pretty much all changes are in conflict, and reconstructing things by hand turns out easier.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_git</id>
		<title>Short Notes on git</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_git"/>
				<updated>2021-03-20T01:52:27Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Basic Commands ==&lt;br /&gt;
&lt;br /&gt;
The ''git'' has 3 &amp;quot;trees&amp;quot; maintained automatically within your local repo - &amp;quot;working copy&amp;quot; is the files you're actually working on, &amp;quot;index&amp;quot; is kind of staging area, and &amp;quot;head&amp;quot; is your last actual commit.&lt;br /&gt;
You're working on your ''working copy'', then add changes to the ''index'', then push those to ''head'' locally, and finally push those to (remote) repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# two ways to check out a repo; 1) first local, then connect&lt;br /&gt;
$ git init                                   # init local copy&lt;br /&gt;
$ git remote add origin &amp;lt;server&amp;gt;             # connect it to remote&lt;br /&gt;
# or, 2) checkout a remote repo straight away&lt;br /&gt;
$ git clone /path/to/repo                    # create working copy of local repo&lt;br /&gt;
$ git clone user@host:/path/to/repo          # create working copy of remote repo&lt;br /&gt;
&lt;br /&gt;
$ git status                                 # get info about local copy, incl. branch ID, changes, etc.&lt;br /&gt;
&lt;br /&gt;
$ git fetch                                  # download changes but do not integrate in the HEAD&lt;br /&gt;
$ git pull                                   # update the local copy to the latest revision&lt;br /&gt;
$ git pull &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # pull specific branch&lt;br /&gt;
$ git diff &amp;lt;source&amp;gt; &amp;lt;dest&amp;gt;                   # view differences between &amp;quot;source&amp;quot; and &amp;quot;dest&amp;quot; branches&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                         # merge changes from another branch (e.g. &amp;quot;origin/master&amp;quot;)&lt;br /&gt;
                                             # you should merge from remote (&amp;quot;origin&amp;quot;) as your local copy may differ&lt;br /&gt;
&lt;br /&gt;
# set meld as diff and merge tool; use --global to apply globally, not just per-repo&lt;br /&gt;
$ git config difftool meld&lt;br /&gt;
$ git config difftool.prompt false           # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool meld                  # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool.prompt false&lt;br /&gt;
$ git difftool                               # you need to use &amp;quot;difftool&amp;quot; to run meld for diff, not just `git diff`&lt;br /&gt;
$ git mergetool                              # run this only after `git merge` if there are any conflicts to be resolved&lt;br /&gt;
&lt;br /&gt;
# getting the changes to the remote repo&lt;br /&gt;
$ git add [-i] &amp;lt;file&amp;gt;                        # add changes from file(s) to index (-i = interactive)&lt;br /&gt;
$ git commit -m 'message'                    # commit changes from index to head&lt;br /&gt;
$ git push origin master                     # push changes from head to master branch, or&lt;br /&gt;
$ git push &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # push changes to &amp;lt;branch&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ git checkout -- &amp;lt;file&amp;gt;                     # revert file and replace with current HEAD version, exc. of changes added to Index&lt;br /&gt;
$ git fetch origin                           # fetch latest history from server&lt;br /&gt;
$ git reset --hard origin/master             # drop all local changes, incl. those in Index&lt;br /&gt;
&lt;br /&gt;
# branching&lt;br /&gt;
$ git branch -av                             # list existing branches&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                   # create a new branch, and switch to it, or&lt;br /&gt;
$ git checkout &amp;lt;branch&amp;gt;                      # switch to branch (make it your HEAD)&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt; --set-upstream    # make the branch available to others, and set the upstream&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                     # delete local branch&lt;br /&gt;
$ git branch -dr &amp;lt;remote/branch&amp;gt;             # delete remote branch&lt;br /&gt;
&lt;br /&gt;
# other stuff&lt;br /&gt;
$ git tag &amp;lt;tag name&amp;gt; &amp;lt;commit id&amp;gt;             # create tag from a commit&lt;br /&gt;
$ git log --pretty=oneline [--author=&amp;lt;name&amp;gt;] # one-line per commit listing&lt;br /&gt;
$ git log --graph --oneline --decorate --all # ascii tree of branches, tags, ...&lt;br /&gt;
$ git log --name-status                      # list changed files&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;svn:externals&amp;quot; like inclusion of another repo; need to commit this as well&lt;br /&gt;
$ git submodule add -b &amp;lt;branch&amp;gt; &amp;lt;repo&amp;gt; [&amp;lt;folder&amp;gt;]&lt;br /&gt;
$ git add &amp;lt;folder&amp;gt; .gitmodules ; + commit ; + push&lt;br /&gt;
&lt;br /&gt;
$ git submodule update --remote              # update the submodules from their respective repo's&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Typical Flow ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone [remote repo]                     # get a local copy of the repo&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                    # start a new branch&lt;br /&gt;
$ git push --set-upstream origin &amp;lt;branch&amp;gt;     # set remote as upstream, to be able to push to remote repo&lt;br /&gt;
&lt;br /&gt;
# do your changes...&lt;br /&gt;
$ git add &amp;lt;files&amp;gt;                             # register changes for commit&lt;br /&gt;
$ git commit -m 'message'&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt;                    # commit the branch with changes to repo&lt;br /&gt;
# repeat as needed...&lt;br /&gt;
&lt;br /&gt;
# once done with the branch&lt;br /&gt;
$ git merge master                            # pull all changes from &amp;quot;master&amp;quot;&lt;br /&gt;
$ git mergetool                               # resolve conflicts; commit again to branch if needed - `add`, `commit`, `push`&lt;br /&gt;
$ git checkout master                         # switch to master&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                          # this should pass ok; commit to &amp;quot;master&amp;quot; afterwards&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                      # clean up - remove the branch&lt;br /&gt;
$ git tag &amp;lt;tag&amp;gt; &amp;lt;commit id&amp;gt;                   # optionally, also tag the commit after merging&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resolve Conflict ===&lt;br /&gt;
&lt;br /&gt;
If on &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; you get a message:&lt;br /&gt;
&amp;lt;pre&amp;gt;error: Your local changes to the following files would be overwritten by merge:&lt;br /&gt;
	[list of files]&lt;br /&gt;
Please, commit your changes or stash them before you can merge.&lt;br /&gt;
Aborting&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to resolve the conflict manually.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git fetch&lt;br /&gt;
git add [file]&lt;br /&gt;
git commit -m 'resolving'&lt;br /&gt;
git merge&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At which point you'll get message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Auto-merging [files]&lt;br /&gt;
CONFLICT (content): Merge conflict in [files]&lt;br /&gt;
Automatic merge failed; fix conflicts and then commit the result.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you need to manually edit the file(s) to resolve the conflict, and then &amp;lt;tt&amp;gt;add/commit&amp;lt;/tt&amp;gt; the resolved file(s).&lt;br /&gt;
&lt;br /&gt;
== Small Tips ==&lt;br /&gt;
&lt;br /&gt;
=== Skip Retyping Your Password ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git config --global credential.helper store&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; and enter your username and password. These will be stored in &amp;lt;tt&amp;gt;~/.git-credentials&amp;lt;/tt&amp;gt; file and reused each time.&lt;br /&gt;
&lt;br /&gt;
=== Ignoring Files and Folders ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ touch .gitignore&lt;br /&gt;
# edit the file with your fave editor (folders should end with '/'):&lt;br /&gt;
folder/&lt;br /&gt;
file.txt&lt;br /&gt;
&lt;br /&gt;
# it's good practice to commit the file as well&lt;br /&gt;
$ git add .gitignore&lt;br /&gt;
$ git commit -m &amp;quot;Added .gitignore file&amp;quot;&lt;br /&gt;
$ git push origin master&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Current Branch ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git rev-parse --abbrev-ref HEAD&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can add this to &amp;lt;tt&amp;gt;.git/config&amp;lt;/tt&amp;gt; as alias:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;[alias]&lt;br /&gt;
current = rev-parse --abbrev-ref HEAD&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and then use it as&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git current&lt;br /&gt;
&amp;gt; master&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Set ''meld'' as your &amp;lt;tt&amp;gt;difftool&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edit your &amp;lt;tt&amp;gt;~/.gitconfig&amp;lt;/tt&amp;gt; file as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;[diff]&lt;br /&gt;
    tool = meld&lt;br /&gt;
[difftool]&lt;br /&gt;
    prompt = false&lt;br /&gt;
[difftool &amp;quot;meld&amp;quot;]&lt;br /&gt;
    cmd = meld &amp;quot;$LOCAL&amp;quot; &amp;quot;$REMOTE&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, running &amp;lt;tt&amp;gt;git difftool&amp;lt;/tt&amp;gt; will bring up your dear ol' ''meld''.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_git</id>
		<title>Short Notes on git</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_git"/>
				<updated>2021-02-20T12:16:55Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Basic Commands ==&lt;br /&gt;
&lt;br /&gt;
The ''git'' has 3 &amp;quot;trees&amp;quot; maintained automatically within your local repo - &amp;quot;working copy&amp;quot; is the files you're actually working on, &amp;quot;index&amp;quot; is kind of staging area, and &amp;quot;head&amp;quot; is your last actual commit.&lt;br /&gt;
You're working on your ''working copy'', then add changes to the ''index'', then push those to ''head'' locally, and finally push those to (remote) repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# two ways to check out a repo; 1) first local, then connect&lt;br /&gt;
$ git init                                   # init local copy&lt;br /&gt;
$ git remote add origin &amp;lt;server&amp;gt;             # connect it to remote&lt;br /&gt;
# or, 2) checkout a remote repo straight away&lt;br /&gt;
$ git clone /path/to/repo                    # create working copy of local repo&lt;br /&gt;
$ git clone user@host:/path/to/repo          # create working copy of remote repo&lt;br /&gt;
&lt;br /&gt;
$ git status                                 # get info about local copy, incl. branch ID, changes, etc.&lt;br /&gt;
&lt;br /&gt;
$ git fetch                                  # download changes but do not integrate in the HEAD&lt;br /&gt;
$ git pull                                   # update the local copy to the latest revision&lt;br /&gt;
$ git pull &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # pull specific branch&lt;br /&gt;
$ git diff &amp;lt;source&amp;gt; &amp;lt;dest&amp;gt;                   # view differences between &amp;quot;source&amp;quot; and &amp;quot;dest&amp;quot; branches&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                         # merge changes from another branch (e.g. &amp;quot;origin/master&amp;quot;)&lt;br /&gt;
                                             # you should merge from remote (&amp;quot;origin&amp;quot;) as your local copy may differ&lt;br /&gt;
&lt;br /&gt;
# set meld as diff and merge tool; use --global to apply globally, not just per-repo&lt;br /&gt;
$ git config difftool meld&lt;br /&gt;
$ git config difftool.prompt false           # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool meld                  # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool.prompt false&lt;br /&gt;
$ git difftool                               # you need to use &amp;quot;difftool&amp;quot; to run meld for diff, not just `git diff`&lt;br /&gt;
$ git mergetool                              # run this only after `git merge` if there are any conflicts to be resolved&lt;br /&gt;
&lt;br /&gt;
# getting the changes to the remote repo&lt;br /&gt;
$ git add [-i] &amp;lt;file&amp;gt;                        # add changes from file(s) to index (-i = interactive)&lt;br /&gt;
$ git commit -m 'message'                    # commit changes from index to head&lt;br /&gt;
$ git push origin master                     # push changes from head to master branch, or&lt;br /&gt;
$ git push &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # push changes to &amp;lt;branch&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ git checkout -- &amp;lt;file&amp;gt;                     # revert file and replace with current HEAD version, exc. of changes added to Index&lt;br /&gt;
$ git fetch origin                           # fetch latest history from server&lt;br /&gt;
$ git reset --hard origin/master             # drop all local changes, incl. those in Index&lt;br /&gt;
&lt;br /&gt;
# branching&lt;br /&gt;
$ git branch -av                             # list existing branches&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                   # create a new branch, and switch to it, or&lt;br /&gt;
$ git checkout &amp;lt;branch&amp;gt;                      # switch to branch (make it your HEAD)&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt; --set-upstream    # make the branch available to others, and set the upstream&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                     # delete local branch&lt;br /&gt;
$ git branch -dr &amp;lt;remote/branch&amp;gt;             # delete remote branch&lt;br /&gt;
&lt;br /&gt;
# other stuff&lt;br /&gt;
$ git tag &amp;lt;tag name&amp;gt; &amp;lt;commit id&amp;gt;             # create tag from a commit&lt;br /&gt;
$ git log --pretty=oneline [--author=&amp;lt;name&amp;gt;] # one-line per commit listing&lt;br /&gt;
$ git log --graph --oneline --decorate --all # ascii tree of branches, tags, ...&lt;br /&gt;
$ git log --name-status                      # list changed files&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;svn:externals&amp;quot; like inclusion of another repo; need to commit this as well&lt;br /&gt;
$ git submodule add -b &amp;lt;branch&amp;gt; &amp;lt;repo&amp;gt; [&amp;lt;folder&amp;gt;]&lt;br /&gt;
$ git add &amp;lt;folder&amp;gt; .gitmodules ; + commit ; + push&lt;br /&gt;
&lt;br /&gt;
$ git submodule update --remote              # update the submodules from their respective repo's&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Typical Flow ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone [remote repo]                     # get a local copy of the repo&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                    # start a new branch&lt;br /&gt;
$ git push --set-upstream origin &amp;lt;branch&amp;gt;     # set remote as upstream, to be able to push to remote repo&lt;br /&gt;
&lt;br /&gt;
# do your changes...&lt;br /&gt;
$ git add &amp;lt;files&amp;gt;                             # register changes for commit&lt;br /&gt;
$ git commit -m 'message'&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt;                    # commit the branch with changes to repo&lt;br /&gt;
# repeat as needed...&lt;br /&gt;
&lt;br /&gt;
# once done with the branch&lt;br /&gt;
$ git merge master                            # pull all changes from &amp;quot;master&amp;quot;&lt;br /&gt;
$ git mergetool                               # resolve conflicts; commit again to branch if needed - `add`, `commit`, `push`&lt;br /&gt;
$ git checkout master                         # switch to master&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                          # this should pass ok; commit to &amp;quot;master&amp;quot; afterwards&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                      # clean up - remove the branch&lt;br /&gt;
$ git tag &amp;lt;tag&amp;gt; &amp;lt;commit id&amp;gt;                   # optionally, also tag the commit after merging&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resolve Conflict ===&lt;br /&gt;
&lt;br /&gt;
If on &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; you get a message:&lt;br /&gt;
&amp;lt;pre&amp;gt;error: Your local changes to the following files would be overwritten by merge:&lt;br /&gt;
	[list of files]&lt;br /&gt;
Please, commit your changes or stash them before you can merge.&lt;br /&gt;
Aborting&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to resolve the conflict manually.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git fetch&lt;br /&gt;
git add [file]&lt;br /&gt;
git commit -m 'resolving'&lt;br /&gt;
git merge&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At which point you'll get message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Auto-merging [files]&lt;br /&gt;
CONFLICT (content): Merge conflict in [files]&lt;br /&gt;
Automatic merge failed; fix conflicts and then commit the result.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you need to manually edit the file(s) to resolve the conflict, and then &amp;lt;tt&amp;gt;add/commit&amp;lt;/tt&amp;gt; the resolved file(s).&lt;br /&gt;
&lt;br /&gt;
== Small Tips ==&lt;br /&gt;
&lt;br /&gt;
=== Skip Retyping Your Password ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git config --global credential.helper store&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; and enter your username and password. These will be stored in &amp;lt;tt&amp;gt;~/.git-credentials&amp;lt;/tt&amp;gt; file and reused each time.&lt;br /&gt;
&lt;br /&gt;
=== Ignoring Files and Folders ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ touch .gitignore&lt;br /&gt;
# edit the file with your fave editor (folders should end with '/'):&lt;br /&gt;
folder/&lt;br /&gt;
file.txt&lt;br /&gt;
&lt;br /&gt;
# it's good practice to commit the file as well&lt;br /&gt;
$ git add .gitignore&lt;br /&gt;
$ git commit -m &amp;quot;Added .gitignore file&amp;quot;&lt;br /&gt;
$ git push origin master&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Current Branch ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git rev-parse --abbrev-ref HEAD&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can add this to &amp;lt;tt&amp;gt;.git/config&amp;lt;/tt&amp;gt; as alias:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;[alias]&lt;br /&gt;
current = rev-parse --abbrev-ref HEAD&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and then use it as&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git current&lt;br /&gt;
&amp;gt; master&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2021-01-25T22:05:50Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Up-to-Date Versions of Packages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&lt;br /&gt;
$ jul () { date -d &amp;quot;$1-01-01 +$2 days -1 day&amp;quot; &amp;quot;+%Y%m%d&amp;quot;; }   - `jul $year $daynum` prints $daynum's day of $year, with Jan 1st being day 1&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
* ''convert album contained in APE or similar file with CUE into separate MP3 tracks''&lt;br /&gt;
 ffmpeg -i cd.ape -ab 256k cd.mp3&lt;br /&gt;
 mp3splt -a -c cd.cue cd.mp3&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on JS|All things JS - React, Vue, ...]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PSQL|PSQL, Postgres, PostgreSQL]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7 python3.7-venv&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
'''update''' - available as a ''snap'' as well, no need to add ''apt'' sources - https://node.dev/node-binary&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_JS</id>
		<title>Short Notes on JS</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_JS"/>
				<updated>2020-12-11T20:12:38Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Simple Mapping ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
let a = {a: 1, b: 2, c: 3};&lt;br /&gt;
&lt;br /&gt;
Object.keys(a).map(i =&amp;gt; console.log(i));&lt;br /&gt;
&amp;gt; a&lt;br /&gt;
&amp;gt; b&lt;br /&gt;
&amp;gt; c&lt;br /&gt;
&amp;gt;&amp;gt; [undefined, undefined, undefined]&lt;br /&gt;
&lt;br /&gt;
a = [1, 2, 3];&lt;br /&gt;
a.map((i, k) =&amp;gt; console.log(i, k));&lt;br /&gt;
&amp;gt; 1 0&lt;br /&gt;
&amp;gt; 2 1&lt;br /&gt;
&amp;gt; 3 2&lt;br /&gt;
&amp;gt;&amp;gt; [undefined, undefined, undefined]&lt;br /&gt;
&lt;br /&gt;
// fill() is required here, as it materializes the Array;&lt;br /&gt;
// otherwise, Array(8) would be treated as empty array by map()&lt;br /&gt;
Array(8).fill().map((_, i) =&amp;gt; i * i);&lt;br /&gt;
&amp;gt;&amp;gt; [0, 1, 4, 9, 16, 25, 36, 49]&lt;br /&gt;
&lt;br /&gt;
== Fetch Patterns ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;fetch(&amp;quot;url&amp;quot;, { options... })&lt;br /&gt;
  .then((response) =&amp;gt; {&lt;br /&gt;
    if (!response.ok)&lt;br /&gt;
      throw new Error('Network response was not ok');&lt;br /&gt;
    return response.json();  // or response.blob(), etc.&lt;br /&gt;
  })&lt;br /&gt;
  .then((data) =&amp;gt; {&lt;br /&gt;
    // do something with the data received&lt;br /&gt;
  })&lt;br /&gt;
  .catch((error) =&amp;gt; {&lt;br /&gt;
    console.error('Failed to fetch:', error);&lt;br /&gt;
  });&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Environment Variables in WebPack ==&lt;br /&gt;
&lt;br /&gt;
WebPack does not have access to environment (duh), so you need to &amp;quot;bake&amp;quot; any relevant environment variables in the WebPack during build:&lt;br /&gt;
&amp;lt;pre&amp;gt;new webpack.DefinePlugin({&lt;br /&gt;
  'process.env': {&lt;br /&gt;
    NODE_ENV: JSON.stringify(process.env.NODE_ENV),&lt;br /&gt;
    STAGE: JSON.stringify(process.env.STAGE),&lt;br /&gt;
    // ...&lt;br /&gt;
  }&lt;br /&gt;
})&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging in VS Code on Linux ==&lt;br /&gt;
&lt;br /&gt;
* install ''Debugger for Chrome'' extension&lt;br /&gt;
* open the ''launch.json'' file, and edit as follows:&lt;br /&gt;
** custom profile - ''user-data-dir'' - is used, to make sure you have clean (enough) slate&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  // Use IntelliSense to learn about possible attributes.&lt;br /&gt;
  // Hover to view descriptions of existing attributes.&lt;br /&gt;
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;0.2.0&amp;quot;,&lt;br /&gt;
  &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;chrome&amp;quot;,&lt;br /&gt;
      &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
      &amp;quot;runtimeExecutable&amp;quot;: &amp;quot;/usr/bin/chromium-browser&amp;quot;,&lt;br /&gt;
      &amp;quot;runtimeArgs&amp;quot;: [&amp;quot;--remote-debugging-port=9222&amp;quot;, &amp;quot;--user-data-dir=/home/user/tmp/remote-profile&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Launch Chrome against localhost&amp;quot;,&lt;br /&gt;
      &amp;quot;url&amp;quot;: &amp;quot;http://localhost:3000&amp;quot;,&lt;br /&gt;
      &amp;quot;webRoot&amp;quot;: &amp;quot;${workspaceFolder}&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run the npm (the port used should correspond to the ''url'' key above)&lt;br /&gt;
* hit debug in VS Code, add breakpoints, etc., and enjoy!&lt;br /&gt;
** this will actually open new browser window, as subwindow of VS Code, neat!&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-12-04T13:01:41Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* SQLAlchemy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Miscellaneous ==&lt;br /&gt;
&lt;br /&gt;
=== Date, Time, Datetime ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;d: datetime.date = ...&lt;br /&gt;
t: datetime.time = ...&lt;br /&gt;
dt: datetime.datetime = ...&lt;br /&gt;
&lt;br /&gt;
dt.date() -&amp;gt; datetime.date&lt;br /&gt;
dt.time() -&amp;gt; datetime.time&lt;br /&gt;
datetime.datetime.combine(d, t) -&amp;gt; datetime.datetime&lt;br /&gt;
in particular: datetime.datetime.combine(d, datetime.time(0, 0, 0)) -&amp;gt; start of date `d` as datetime&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;strftime()&amp;lt;/tt&amp;gt; Formatting ===&lt;br /&gt;
&lt;br /&gt;
Examples for ''Thu Dec 3, 2020, 01:23:45.678'' - &amp;lt;tt&amp;gt;datetime.datetime(2020, 12, 3, 1, 23, 45, 678000)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%y       - year (20)&lt;br /&gt;
%Y       - year (2020)&lt;br /&gt;
%m / %-m - month zero-/un- padded (12 / 12)&lt;br /&gt;
%d / %-d - day zero-/un- padded (03 / 3)&lt;br /&gt;
%H / %-H - hour zero-/un- padded, 24-hour clock (01 / 1)&lt;br /&gt;
%I / %-I - hour zero-/un- padded, 12-hour clock (01 / 1)&lt;br /&gt;
%p       - time of day (AM)&lt;br /&gt;
%M / %-M - minute zero-/un- padded (23 / 23)&lt;br /&gt;
%S / %-S - second zero-/un- padded (45 / 45)&lt;br /&gt;
%f       - microsecond (678000)&lt;br /&gt;
%z       - timezone as +HHMM or -HHMM, empty if object is naive&lt;br /&gt;
%Z       - timezone name, empty if object is naive&lt;br /&gt;
%j / %-j - day of year zero-/un- padded (338 / 338)&lt;br /&gt;
%a / %A  - weekday name, abb. / full (Thu / Thursday)&lt;br /&gt;
%w       - weekday as decimal, 0-Sunday, 6-Saturday (4)&lt;br /&gt;
%U / %W  - week number, week starting on Sunday / Monday (48 / 48)&lt;br /&gt;
%b / %B  - month name, abb. / full (Dec / December)&lt;br /&gt;
%c       - locale appropriate date and time representation (Thu Dec  3 01:23:45 2020)&lt;br /&gt;
%x       - locale appropriate date representation (12/03/20)&lt;br /&gt;
%X       - locale appropriate time representation (01:23:45)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Select, Where, Group ===&lt;br /&gt;
&lt;br /&gt;
=== Updating ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
session.query(Table).\&lt;br /&gt;
    filter(Table.id.in_(...)).\&lt;br /&gt;
    update({&lt;br /&gt;
        Table.column1: 10,&lt;br /&gt;
        Table.column2: Table.column2 + 50&lt;br /&gt;
    })&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scalar Values ===&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;min&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;max&amp;lt;/tt&amp;gt;, ... ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from sqlalchemy import func&lt;br /&gt;
&lt;br /&gt;
max_value = session.query(sqlalchemy.func.max(Table.column)).scalar()&lt;br /&gt;
&lt;br /&gt;
# or, for multiple, just use&lt;br /&gt;
session.query(sqlalchemy.func.min(Table.column), sqlalchemy.func.max(Table.column)).first()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model, including Indexes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable, CreateIndex&lt;br /&gt;
from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
def print_create_statement(model):&lt;br /&gt;
    print(CreateTable(model.__table__).compile(dialect=postgresql.dialect()))&lt;br /&gt;
    for index in model.__table__.indexes:&lt;br /&gt;
        print(CreateIndex(index).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-12-03T11:55:16Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Miscellaneous ==&lt;br /&gt;
&lt;br /&gt;
=== Date, Time, Datetime ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;d: datetime.date = ...&lt;br /&gt;
t: datetime.time = ...&lt;br /&gt;
dt: datetime.datetime = ...&lt;br /&gt;
&lt;br /&gt;
dt.date() -&amp;gt; datetime.date&lt;br /&gt;
dt.time() -&amp;gt; datetime.time&lt;br /&gt;
datetime.datetime.combine(d, t) -&amp;gt; datetime.datetime&lt;br /&gt;
in particular: datetime.datetime.combine(d, datetime.time(0, 0, 0)) -&amp;gt; start of date `d` as datetime&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;strftime()&amp;lt;/tt&amp;gt; Formatting ===&lt;br /&gt;
&lt;br /&gt;
Examples for ''Thu Dec 3, 2020, 01:23:45.678'' - &amp;lt;tt&amp;gt;datetime.datetime(2020, 12, 3, 1, 23, 45, 678000)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
%y       - year (20)&lt;br /&gt;
%Y       - year (2020)&lt;br /&gt;
%m / %-m - month zero-/un- padded (12 / 12)&lt;br /&gt;
%d / %-d - day zero-/un- padded (03 / 3)&lt;br /&gt;
%H / %-H - hour zero-/un- padded, 24-hour clock (01 / 1)&lt;br /&gt;
%I / %-I - hour zero-/un- padded, 12-hour clock (01 / 1)&lt;br /&gt;
%p       - time of day (AM)&lt;br /&gt;
%M / %-M - minute zero-/un- padded (23 / 23)&lt;br /&gt;
%S / %-S - second zero-/un- padded (45 / 45)&lt;br /&gt;
%f       - microsecond (678000)&lt;br /&gt;
%z       - timezone as +HHMM or -HHMM, empty if object is naive&lt;br /&gt;
%Z       - timezone name, empty if object is naive&lt;br /&gt;
%j / %-j - day of year zero-/un- padded (338 / 338)&lt;br /&gt;
%a / %A  - weekday name, abb. / full (Thu / Thursday)&lt;br /&gt;
%w       - weekday as decimal, 0-Sunday, 6-Saturday (4)&lt;br /&gt;
%U / %W  - week number, week starting on Sunday / Monday (48 / 48)&lt;br /&gt;
%b / %B  - month name, abb. / full (Dec / December)&lt;br /&gt;
%c       - locale appropriate date and time representation (Thu Dec  3 01:23:45 2020)&lt;br /&gt;
%x       - locale appropriate date representation (12/03/20)&lt;br /&gt;
%X       - locale appropriate time representation (01:23:45)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Some Basics ===&lt;br /&gt;
&lt;br /&gt;
==== Select, Where, Group ====&lt;br /&gt;
&lt;br /&gt;
==== Updating ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
session.query(Table).\&lt;br /&gt;
    filter(Table.id.in_(...)).\&lt;br /&gt;
    update({&lt;br /&gt;
        Table.column1: 10,&lt;br /&gt;
        Table.column2: Table.column2 + 50&lt;br /&gt;
    })&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Scalar Values ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
max_value = session.query(sqlalchemy.func.max(Table.column)).scalar()&lt;br /&gt;
&lt;br /&gt;
# or, for multiple, just use&lt;br /&gt;
session.query(sqlalchemy.func.min(Table.column), sqlalchemy.func.max(Table.column)).first()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model, including Indexes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable, CreateIndex&lt;br /&gt;
from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
def print_create_statement(model):&lt;br /&gt;
    print(CreateTable(model.__table__).compile(dialect=postgresql.dialect()))&lt;br /&gt;
    for index in model.__table__.indexes:&lt;br /&gt;
        print(CreateIndex(index).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-12-03T01:53:06Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Miscellaneous ==&lt;br /&gt;
&lt;br /&gt;
=== Date, Time, Datetime ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;d: datetime.date = ...&lt;br /&gt;
t: datetime.time = ...&lt;br /&gt;
dt: datetime.datetime = ...&lt;br /&gt;
&lt;br /&gt;
dt.date() -&amp;gt; datetime.date&lt;br /&gt;
dt.time() -&amp;gt; datetime.time&lt;br /&gt;
datetime.datetime.combine(d, t) -&amp;gt; datetime.datetime&lt;br /&gt;
in particular: datetime.datetime.combine(d, datetime.time(0, 0, 0)) -&amp;gt; start of date `d` as datetime&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Some Basics ===&lt;br /&gt;
&lt;br /&gt;
==== Select, Where, Group ====&lt;br /&gt;
&lt;br /&gt;
==== Updating ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
session.query(Table).\&lt;br /&gt;
    filter(Table.id.in_(...)).\&lt;br /&gt;
    update({&lt;br /&gt;
        Table.column1: 10,&lt;br /&gt;
        Table.column2: Table.column2 + 50&lt;br /&gt;
    })&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Scalar Values ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
max_value = session.query(sqlalchemy.func.max(Table.column)).scalar()&lt;br /&gt;
&lt;br /&gt;
# or, for multiple, just use&lt;br /&gt;
session.query(sqlalchemy.func.min(Table.column), sqlalchemy.func.max(Table.column)).first()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model, including Indexes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable, CreateIndex&lt;br /&gt;
from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
def print_create_statement(model):&lt;br /&gt;
    print(CreateTable(model.__table__).compile(dialect=postgresql.dialect()))&lt;br /&gt;
    for index in model.__table__.indexes:&lt;br /&gt;
        print(CreateIndex(index).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_PSQL</id>
		<title>Short Notes on PSQL</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_PSQL"/>
				<updated>2020-10-02T12:10:19Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;PSQL aka Postgres aka PostgreSQL... I prefer psql.&lt;br /&gt;
&lt;br /&gt;
== Dump and Restore ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;dump:&lt;br /&gt;
$ pg_dump -h host -p 5432 -U user -F c -b -v -f /tmp/db_name.backup db_name&lt;br /&gt;
restore:&lt;br /&gt;
$ pg_restore -h host -p 5432 -U user -d db_name -v /tmp/db_name.backup&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Delete Duplicate Lines ==&lt;br /&gt;
&lt;br /&gt;
Before you can add a &amp;lt;tt&amp;gt;unique&amp;lt;/tt&amp;gt; constraint to a table, you have to make sure it does satisfy this criteria.&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;table_T&amp;lt;/tt&amp;gt; and columns &amp;lt;tt&amp;gt;criteria_1&amp;lt;/tt&amp;gt;, ..., &amp;lt;tt&amp;gt;criteria_N&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;;&lt;br /&gt;
;; list rows that do not satisfy the uniqueness constraint&lt;br /&gt;
;;&lt;br /&gt;
SELECT&lt;br /&gt;
    criteria_1,&lt;br /&gt;
    ...&lt;br /&gt;
    criteria_N,&lt;br /&gt;
    COUNT(*)&lt;br /&gt;
FROM&lt;br /&gt;
    table_T&lt;br /&gt;
GROUP BY&lt;br /&gt;
    criteria_1, ..., criteria_N&lt;br /&gt;
HAVING&lt;br /&gt;
    COUNT(*) &amp;gt; 1&lt;br /&gt;
ORDER BY&lt;br /&gt;
    criteria_1, ..., criteria_N;&lt;br /&gt;
&lt;br /&gt;
;;&lt;br /&gt;
;; delete all rows that do not satisfy the constraint, keeping the ones with lowest id value&lt;br /&gt;
;;&lt;br /&gt;
DELETE  FROM&lt;br /&gt;
    table_T a&lt;br /&gt;
        USING table_T b&lt;br /&gt;
WHERE&lt;br /&gt;
    a.id &amp;gt; b.id&lt;br /&gt;
    AND a.criteria_1 = b.criteria_1&lt;br /&gt;
    ...&lt;br /&gt;
    AND a.criteria_N = b.criteria_N;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-08-07T01:24:39Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Some Basics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Some Basics ===&lt;br /&gt;
&lt;br /&gt;
==== Select, Where, Group ====&lt;br /&gt;
&lt;br /&gt;
==== Updating ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
session.query(Table).\&lt;br /&gt;
    filter(Table.id.in_(...)).\&lt;br /&gt;
    update({&lt;br /&gt;
        Table.column1: 10,&lt;br /&gt;
        Table.column2: Table.column2 + 50&lt;br /&gt;
    })&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Scalar Values ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
max_value = session.query(sqlalchemy.func.max(Table.column)).scalar()&lt;br /&gt;
&lt;br /&gt;
# or, for multiple, just use&lt;br /&gt;
session.query(sqlalchemy.func.min(Table.column), sqlalchemy.func.max(Table.column)).first()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model, including Indexes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable, CreateIndex&lt;br /&gt;
from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
def print_create_statement(model):&lt;br /&gt;
    print(CreateTable(model.__table__).compile(dialect=postgresql.dialect()))&lt;br /&gt;
    for index in model.__table__.indexes:&lt;br /&gt;
        print(CreateIndex(index).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-08-06T21:39:02Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* SQLAlchemy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Some Basics ===&lt;br /&gt;
&lt;br /&gt;
==== Updating ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
session.query(model).\&lt;br /&gt;
    filter(...).\&lt;br /&gt;
    update({model.col1: 10, model.col2: model.col2 + 50})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model, including Indexes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable, CreateIndex&lt;br /&gt;
from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
def print_create_statement(model):&lt;br /&gt;
    print(CreateTable(model.__table__).compile(dialect=postgresql.dialect()))&lt;br /&gt;
    for index in model.__table__.indexes:&lt;br /&gt;
        print(CreateIndex(index).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-07-30T11:52:25Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* SQLAlchemy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model, including Indexes ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable, CreateIndex&lt;br /&gt;
from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
def print_create_statement(model):&lt;br /&gt;
    print(CreateTable(model.__table__).compile(dialect=postgresql.dialect()))&lt;br /&gt;
    for index in model.__table__.indexes:&lt;br /&gt;
        print(CreateIndex(index).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-07-14T21:06:34Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* SQLAlchemy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable&lt;br /&gt;
&lt;br /&gt;
with db_session():&lt;br /&gt;
    print(CreateTable(MyModel.__table__))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or, without actually instantiating an engine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
print(CreateTable(MyModel.__table__).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Subqueries ===&lt;br /&gt;
&lt;br /&gt;
Creating subqueries is pretty straightforward in SQLAlchemy.&lt;br /&gt;
&lt;br /&gt;
To emit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT sub.c1, sub.c2&lt;br /&gt;
FROM (SELECT x as c1, y as c2 FROM table) AS sub&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
you define the &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt; and then query on it as usual, with the exception of bit more explicit access to columns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sub = session.query(table.x.label('c1'),&lt;br /&gt;
                    table.y.label('c2')).\&lt;br /&gt;
    cte('sub')&lt;br /&gt;
&lt;br /&gt;
res = session.query(sub.c.c1, sub.c.c2).\&lt;br /&gt;
    all()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_AWS</id>
		<title>Short Notes on AWS</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_AWS"/>
				<updated>2020-05-20T16:56:34Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* AWS Chalice */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Can't connect to EC2 instance ==&lt;br /&gt;
&lt;br /&gt;
The obvious 2 problems with incoming requests, that are outside of AWS's scope:&lt;br /&gt;
* check the instance's firewall&lt;br /&gt;
* check that the app is listening to all incoming (0.0.0.0/0 or your IP, not just 127.0.0.1)&lt;br /&gt;
&lt;br /&gt;
On the AWS side, check the following:&lt;br /&gt;
* make sure the Elastic IP is associated with the instance&lt;br /&gt;
** find the instance in the EC2 &amp;gt; Instances&lt;br /&gt;
** look under Description tab, Elastic IP&lt;br /&gt;
** if it's not, go to EC2 &amp;gt; Elastic IPs&lt;br /&gt;
** choose Elastic IP from the list (or, allocate new on) that is not associated with any instance&lt;br /&gt;
** choose Actions &amp;gt; Associate address, and associate it with the instance&lt;br /&gt;
* make sure Security group permissions allow the connection&lt;br /&gt;
** go to EC2 &amp;gt; Security Groups&lt;br /&gt;
** select the security group (you can find which security group instance is in in the list on EC2 &amp;gt; Instances page, last column)&lt;br /&gt;
** on the Inbound tab, check that your protocol is enabled for Source 0.0.0.0/0 (or from your IP)&lt;br /&gt;
* make sure your Internet Gateway is connected to your VPC&lt;br /&gt;
** make sure the Internet Gateway is attached to your VPC, under VPC &amp;gt; Internet Gateways &amp;gt; Summary tab&lt;br /&gt;
** go to VPC &amp;gt; Route Tables, select route table for your VPC&lt;br /&gt;
** under Routes tab, make sure that route with destination 0.0.0.0/0, with Target being your internet gateway, exists and is Active&lt;br /&gt;
&lt;br /&gt;
== Authorization header being removed by ElasticBeanstalk ==&lt;br /&gt;
&lt;br /&gt;
By default, AWS ElasticBeanstalk's WSGI server strips &amp;lt;code&amp;gt;Authorization&amp;lt;/code&amp;gt; header from requests.&lt;br /&gt;
&lt;br /&gt;
To get these back, just plug your wsgi config file through &amp;lt;code&amp;gt;.ebextensions&amp;lt;/code&amp;gt;, adding a &amp;lt;code&amp;gt;wsgi.authorization.config&amp;lt;/code&amp;gt; file, with the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;files:&lt;br /&gt;
    &amp;quot;/etc/httpd/conf.d/wsgiauth.conf&amp;quot;:&lt;br /&gt;
        mode: &amp;quot;000644&amp;quot;&lt;br /&gt;
        owner: root&lt;br /&gt;
        group: root&lt;br /&gt;
        content: |&lt;br /&gt;
            WSGIPassAuthorization On&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IAM Notes ==&lt;br /&gt;
&lt;br /&gt;
* you need policy AmazonRDSReadOnlyAccess for your IAM to be able to list RDS instances&lt;br /&gt;
&lt;br /&gt;
== AWS Lambda (Py) Notes ==&lt;br /&gt;
&lt;br /&gt;
For &amp;lt;tt&amp;gt;handler(event, context)&amp;lt;/tt&amp;gt; function, parameters are in:&lt;br /&gt;
&lt;br /&gt;
* GET parameters in &amp;lt;tt&amp;gt;event[&amp;quot;multiValueQueryStringParameters&amp;quot;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
** ''note'': parameters are stored in arrays, the lambda's parser correctly presumes that there may be multiple values; e.g. &amp;lt;tt&amp;gt;event[&amp;quot;multiValueQueryStringParameters&amp;quot;] = {&amp;quot;param&amp;quot;: [&amp;quot;value&amp;quot;]}&amp;lt;/tt&amp;gt;&lt;br /&gt;
* path parameters in &amp;lt;tt&amp;gt;event[&amp;quot;pathParameters&amp;quot;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
** ''note'': path parameters are specified in the SAM ''yaml'', under &amp;lt;tt&amp;gt;Path&amp;lt;/tt&amp;gt; property, as &amp;lt;tt&amp;gt;Path: /v1/user/{user_id}/data/&amp;lt;/tt&amp;gt;&lt;br /&gt;
* POST/PUT body in &amp;lt;tt&amp;gt;event[&amp;quot;body&amp;quot;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
** ''note'': stored as string, you have to &amp;lt;tt&amp;gt;json.loads()&amp;lt;/tt&amp;gt; or similar&lt;br /&gt;
&lt;br /&gt;
== boto3 Snippets ==&lt;br /&gt;
&lt;br /&gt;
=== Generate presigned S3 URL ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;s3 = boto3.client('s3', config=botocore.client.Config(signature_version='s3v4', region_name=BUCKET_REGION))&lt;br /&gt;
resp = s3.generate_presigned_url('get_object', Params={'Bucket': BUCKET, 'Key': KEY}, ExpiresIn=SECONDS)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AWS Chalice ==&lt;br /&gt;
&lt;br /&gt;
Prepare your virtualenv, and install boto3 and Chalice in it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ virtualenv ~/.virtualenvs/test-venv&lt;br /&gt;
$ source ~/.virtualenvs/test-venv/bin/activate&lt;br /&gt;
(test-venv) $ pip install boto3 chalice&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connection to RDS ===&lt;br /&gt;
&lt;br /&gt;
Lambda's are typically not restricted to VPC, while RDS is strictly tied to it.&lt;br /&gt;
You need to assign your Chalice Lambda's to the same subnets as the RDS, and the same security group.&lt;br /&gt;
Chalice does almost all of this for you!&lt;br /&gt;
&lt;br /&gt;
You just need to copy all subnet ID's used by your RDS, and the security group ID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# .chalice/config.json:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;2.0&amp;quot;,&lt;br /&gt;
  &amp;quot;app_name&amp;quot;: &amp;quot;chalice-test&amp;quot;,&lt;br /&gt;
  &amp;quot;environment_variables&amp;quot;: {&lt;br /&gt;
    &amp;quot;var&amp;quot;: &amp;quot;value&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;layers&amp;quot;: [&amp;quot;arn:aws:lambda:...&amp;quot;],&lt;br /&gt;
  &amp;quot;stages&amp;quot;: {&lt;br /&gt;
    &amp;quot;dev&amp;quot;: {&lt;br /&gt;
      &amp;quot;api_gateway_stage&amp;quot;: &amp;quot;api&amp;quot;,&lt;br /&gt;
      &amp;quot;subnet_ids&amp;quot;: [&lt;br /&gt;
        &amp;quot;subnet-...&amp;quot;, ...&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;security_group_ids&amp;quot;: [&lt;br /&gt;
        &amp;quot;sg-...&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Send and Download Binary Files ===&lt;br /&gt;
&lt;br /&gt;
There are two sides of this story, influencing both your Chalice code, and influencing the receiving code (your frontend app).&lt;br /&gt;
&lt;br /&gt;
On the Chalice side, you simply use the &amp;lt;tt&amp;gt;Response&amp;lt;/tt&amp;gt; object with some of the registered binary types. I typically just use &amp;lt;tt&amp;gt;application/octet-stream&amp;lt;/tt&amp;gt;...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@app.route('/binary-data')&lt;br /&gt;
def bin_echo():&lt;br /&gt;
    raw_request_body = app.current_request.raw_body&lt;br /&gt;
    return Response(body=binary_data,&lt;br /&gt;
                    status_code=200,&lt;br /&gt;
                    headers={'Content-Type': 'application/octet-stream'})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[https://chalice.readthedocs.io/en/latest/topics/views.html#binary-content For more info see the Chalice documentation]&lt;br /&gt;
&lt;br /&gt;
On the frontend side, you need to make sure API Gateway does not mess you up - you need to specify &amp;lt;tt&amp;gt;Accept&amp;lt;/tt&amp;gt; header of the binary type (not necessarily of the same type as the one returned from Chalice). If you specify &amp;lt;tt&amp;gt;*/*&amp;lt;/tt&amp;gt; as the accepted type, you'll receive base64 encoded data.&lt;br /&gt;
&lt;br /&gt;
=== Getting 403 on a Route ===&lt;br /&gt;
&lt;br /&gt;
Apart of actual 403 response, Chalice will return 403 on a route that does not have the &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt; prefix:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# this will return 403 :S&lt;br /&gt;
@app.route('v1/test')&lt;br /&gt;
def v1_test():&lt;br /&gt;
    return {}&lt;br /&gt;
&lt;br /&gt;
# this will work :)&lt;br /&gt;
@app.route('/v1/test')&lt;br /&gt;
def v1_test():&lt;br /&gt;
    return {}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Building a Python Layer ==&lt;br /&gt;
&lt;br /&gt;
We'll be using docker Amazon Linux image.&lt;br /&gt;
&lt;br /&gt;
Below, commands starting with &amp;lt;tt&amp;gt;$&amp;lt;/tt&amp;gt; are run on your machine, while those starting with &amp;lt;tt&amp;gt;bash-4.2#&amp;lt;/tt&amp;gt; are run within the docker container.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat docker-compose.yaml &lt;br /&gt;
version: &amp;quot;3&amp;quot;&lt;br /&gt;
services:&lt;br /&gt;
  amzlinux:&lt;br /&gt;
    image: &amp;quot;amazonlinux&amp;quot;&lt;br /&gt;
    command: &amp;quot;sleep infinity&amp;quot;&lt;br /&gt;
    volumes:&lt;br /&gt;
      - ./:/host&lt;br /&gt;
&lt;br /&gt;
$ docker-compose up&lt;br /&gt;
Creating network &amp;quot;layer-example_default&amp;quot; with the default driver&lt;br /&gt;
Pulling amzlinux (amazonlinux:)...&lt;br /&gt;
[...]&lt;br /&gt;
Attaching to layer-example_amzlinux_1&lt;br /&gt;
&lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES&lt;br /&gt;
a5107c00ed35        amazonlinux         &amp;quot;sleep infinity&amp;quot;    10 seconds ago      Up 8 seconds                            '''layer-example_amzlinux_1'''&lt;br /&gt;
&lt;br /&gt;
$ docker exec -it layer-example_amzlinux_1 /bin/bash&lt;br /&gt;
&lt;br /&gt;
bash-4.2# yum -y update&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; bash-4.2# yum -y groupinstall &amp;quot;Development Tools&amp;quot;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; bash-4.2# yum -y install Cython&lt;br /&gt;
&lt;br /&gt;
bash-4.2# yum -y install python3-pip.noarch zip&lt;br /&gt;
[...]&lt;br /&gt;
Installed:&lt;br /&gt;
  python3-pip.noarch 0:9.0.3-1.amzn2.0.1&lt;br /&gt;
&lt;br /&gt;
bash-4.2# cd /host/&lt;br /&gt;
&lt;br /&gt;
bash-4.2# mkdir -p sqlalchemy-layer/python&lt;br /&gt;
&lt;br /&gt;
bash-4.2# pip3 install sqlalchemy -t sqlalchemy-layer/python/&lt;br /&gt;
[...]&lt;br /&gt;
Successfully installed sqlalchemy-1.3.11&lt;br /&gt;
&lt;br /&gt;
bash-4.2# pip3 install psycopg2-binary -t sqlalchemy-layer/python/&lt;br /&gt;
[...]&lt;br /&gt;
Successfully installed psycopg2-binary-2.8.4&lt;br /&gt;
&lt;br /&gt;
bash-4.2# cd sqlalchemy-layer/&lt;br /&gt;
bash-4.2# zip -r aws-sqlalchemy-layer.zip python/ -x \*.pyc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can upload the &amp;lt;tt&amp;gt;aws-sqlalchemy-layer.zip&amp;lt;/tt&amp;gt; as a Layer through AWS console.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2020-05-11T07:17:08Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Up-to-Date Versions of Packages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&lt;br /&gt;
$ jul () { date -d &amp;quot;$1-01-01 +$2 days -1 day&amp;quot; &amp;quot;+%Y%m%d&amp;quot;; }   - `jul $year $daynum` prints $daynum's day of $year, with Jan 1st being day 1&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
* ''convert album contained in APE or similar file with CUE into separate MP3 tracks''&lt;br /&gt;
 ffmpeg -i cd.ape -ab 256k cd.mp3&lt;br /&gt;
 mp3splt -a -c cd.cue cd.mp3&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on JS|All things JS - React, Vue, ...]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PSQL|PSQL, Postgres, PostgreSQL]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7 python3.7-venv&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_git</id>
		<title>Short Notes on git</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_git"/>
				<updated>2020-04-24T19:02:37Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Typical Flow */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Basic Commands ==&lt;br /&gt;
&lt;br /&gt;
The ''git'' has 3 &amp;quot;trees&amp;quot; maintained automatically within your local repo - &amp;quot;working copy&amp;quot; is the files you're actually working on, &amp;quot;index&amp;quot; is kind of staging area, and &amp;quot;head&amp;quot; is your last actual commit.&lt;br /&gt;
You're working on your ''working copy'', then add changes to the ''index'', then push those to ''head'' locally, and finally push those to (remote) repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# two ways to check out a repo; 1) first local, then connect&lt;br /&gt;
$ git init                                   # init local copy&lt;br /&gt;
$ git remote add origin &amp;lt;server&amp;gt;             # connect it to remote&lt;br /&gt;
# or, 2) checkout a remote repo straight away&lt;br /&gt;
$ git clone /path/to/repo                    # create working copy of local repo&lt;br /&gt;
$ git clone user@host:/path/to/repo          # create working copy of remote repo&lt;br /&gt;
&lt;br /&gt;
$ git status                                 # get info about local copy, incl. branch ID, changes, etc.&lt;br /&gt;
&lt;br /&gt;
$ git fetch                                  # download changes but do not integrate in the HEAD&lt;br /&gt;
$ git pull                                   # update the local copy to the latest revision&lt;br /&gt;
$ git pull &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # pull specific branch&lt;br /&gt;
$ git diff &amp;lt;source&amp;gt; &amp;lt;dest&amp;gt;                   # view differences between &amp;quot;source&amp;quot; and &amp;quot;dest&amp;quot; branches&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                         # merge changes from another branch (e.g. &amp;quot;origin/master&amp;quot;)&lt;br /&gt;
                                             # you should merge from remote (&amp;quot;origin&amp;quot;) as your local copy may differ&lt;br /&gt;
&lt;br /&gt;
# set meld as diff and merge tool; use --global to apply globally, not just per-repo&lt;br /&gt;
$ git config difftool meld&lt;br /&gt;
$ git config difftool.prompt false           # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool meld                  # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool.prompt false&lt;br /&gt;
$ git difftool                               # you need to use &amp;quot;difftool&amp;quot; to run meld for diff, not just `git diff`&lt;br /&gt;
$ git mergetool                              # run this only after `git merge` if there are any conflicts to be resolved&lt;br /&gt;
&lt;br /&gt;
# getting the changes to the remote repo&lt;br /&gt;
$ git add [-i] &amp;lt;file&amp;gt;                        # add changes from file(s) to index (-i = interactive)&lt;br /&gt;
$ git commit -m 'message'                    # commit changes from index to head&lt;br /&gt;
$ git push origin master                     # push changes from head to master branch, or&lt;br /&gt;
$ git push &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # push changes to &amp;lt;branch&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ git checkout -- &amp;lt;file&amp;gt;                     # revert file and replace with current HEAD version, exc. of changes added to Index&lt;br /&gt;
$ git fetch origin                           # fetch latest history from server&lt;br /&gt;
$ git reset --hard origin/master             # drop all local changes, incl. those in Index&lt;br /&gt;
&lt;br /&gt;
# branching&lt;br /&gt;
$ git branch -av                             # list existing branches&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                   # create a new branch, and switch to it, or&lt;br /&gt;
$ git checkout &amp;lt;branch&amp;gt;                      # switch to branch (make it your HEAD)&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt; --set-upstream    # make the branch available to others, and set the upstream&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                     # delete local branch&lt;br /&gt;
$ git branch -dr &amp;lt;remote/branch&amp;gt;             # delete remote branch&lt;br /&gt;
&lt;br /&gt;
# other stuff&lt;br /&gt;
$ git tag &amp;lt;tag name&amp;gt; &amp;lt;commit id&amp;gt;             # create tag from a commit&lt;br /&gt;
$ git log --pretty=oneline [--author=&amp;lt;name&amp;gt;] # one-line per commit listing&lt;br /&gt;
$ git log --graph --oneline --decorate --all # ascii tree of branches, tags, ...&lt;br /&gt;
$ git log --name-status                      # list changed files&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;svn:externals&amp;quot; like inclusion of another repo; need to commit this as well&lt;br /&gt;
$ git submodule add -b &amp;lt;branch&amp;gt; &amp;lt;repo&amp;gt; [&amp;lt;folder&amp;gt;]&lt;br /&gt;
$ git add &amp;lt;folder&amp;gt; .gitmodules ; + commit ; + push&lt;br /&gt;
&lt;br /&gt;
$ git submodule update --remote              # update the submodules from their respective repo's&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Typical Flow ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git clone [remote repo]                     # get a local copy of the repo&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                    # start a new branch&lt;br /&gt;
$ git push --set-upstream origin &amp;lt;branch&amp;gt;     # set remote as upstream, to be able to push to remote repo&lt;br /&gt;
&lt;br /&gt;
# do your changes...&lt;br /&gt;
$ git add &amp;lt;files&amp;gt;                             # register changes for commit&lt;br /&gt;
$ git commit -m 'message'&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt;                    # commit the branch with changes to repo&lt;br /&gt;
# repeat as needed...&lt;br /&gt;
&lt;br /&gt;
# once done with the branch&lt;br /&gt;
$ git merge master                            # pull all changes from &amp;quot;master&amp;quot;&lt;br /&gt;
$ git mergetool                               # resolve conflicts; commit again to branch if needed - `add`, `commit`, `push`&lt;br /&gt;
$ git checkout master                         # switch to master&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                          # this should pass ok; commit to &amp;quot;master&amp;quot; afterwards&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                      # clean up - remove the branch&lt;br /&gt;
$ git tag &amp;lt;tag&amp;gt; &amp;lt;commit id&amp;gt;                   # optionally, also tag the commit after merging&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resolve Conflict ===&lt;br /&gt;
&lt;br /&gt;
If on &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; you get a message:&lt;br /&gt;
&amp;lt;pre&amp;gt;error: Your local changes to the following files would be overwritten by merge:&lt;br /&gt;
	[list of files]&lt;br /&gt;
Please, commit your changes or stash them before you can merge.&lt;br /&gt;
Aborting&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to resolve the conflict manually.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git fetch&lt;br /&gt;
git add [file]&lt;br /&gt;
git commit -m 'resolving'&lt;br /&gt;
git merge&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At which point you'll get message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Auto-merging [files]&lt;br /&gt;
CONFLICT (content): Merge conflict in [files]&lt;br /&gt;
Automatic merge failed; fix conflicts and then commit the result.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you need to manually edit the file(s) to resolve the conflict, and then &amp;lt;tt&amp;gt;add/commit&amp;lt;/tt&amp;gt; the resolved file(s).&lt;br /&gt;
&lt;br /&gt;
=== Skip Retyping Your Password ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git config --global credential.helper store&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; and enter your username and password. These will be stored in &amp;lt;tt&amp;gt;~/.git-credentials&amp;lt;/tt&amp;gt; file and reused each time.&lt;br /&gt;
&lt;br /&gt;
=== Ignoring Files and Folders ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ touch .gitignore&lt;br /&gt;
# edit the file with your fave editor (folders should end with '/'):&lt;br /&gt;
folder/&lt;br /&gt;
file.txt&lt;br /&gt;
&lt;br /&gt;
# it's good practice to commit the file as well&lt;br /&gt;
$ git add .gitignore&lt;br /&gt;
$ git commit -m &amp;quot;Added .gitignore file&amp;quot;&lt;br /&gt;
$ git push origin master&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_AWS</id>
		<title>Short Notes on AWS</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_AWS"/>
				<updated>2020-04-20T11:10:14Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* AWS Chalice */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Can't connect to EC2 instance ==&lt;br /&gt;
&lt;br /&gt;
The obvious 2 problems with incoming requests, that are outside of AWS's scope:&lt;br /&gt;
* check the instance's firewall&lt;br /&gt;
* check that the app is listening to all incoming (0.0.0.0/0 or your IP, not just 127.0.0.1)&lt;br /&gt;
&lt;br /&gt;
On the AWS side, check the following:&lt;br /&gt;
* make sure the Elastic IP is associated with the instance&lt;br /&gt;
** find the instance in the EC2 &amp;gt; Instances&lt;br /&gt;
** look under Description tab, Elastic IP&lt;br /&gt;
** if it's not, go to EC2 &amp;gt; Elastic IPs&lt;br /&gt;
** choose Elastic IP from the list (or, allocate new on) that is not associated with any instance&lt;br /&gt;
** choose Actions &amp;gt; Associate address, and associate it with the instance&lt;br /&gt;
* make sure Security group permissions allow the connection&lt;br /&gt;
** go to EC2 &amp;gt; Security Groups&lt;br /&gt;
** select the security group (you can find which security group instance is in in the list on EC2 &amp;gt; Instances page, last column)&lt;br /&gt;
** on the Inbound tab, check that your protocol is enabled for Source 0.0.0.0/0 (or from your IP)&lt;br /&gt;
* make sure your Internet Gateway is connected to your VPC&lt;br /&gt;
** make sure the Internet Gateway is attached to your VPC, under VPC &amp;gt; Internet Gateways &amp;gt; Summary tab&lt;br /&gt;
** go to VPC &amp;gt; Route Tables, select route table for your VPC&lt;br /&gt;
** under Routes tab, make sure that route with destination 0.0.0.0/0, with Target being your internet gateway, exists and is Active&lt;br /&gt;
&lt;br /&gt;
== Authorization header being removed by ElasticBeanstalk ==&lt;br /&gt;
&lt;br /&gt;
By default, AWS ElasticBeanstalk's WSGI server strips &amp;lt;code&amp;gt;Authorization&amp;lt;/code&amp;gt; header from requests.&lt;br /&gt;
&lt;br /&gt;
To get these back, just plug your wsgi config file through &amp;lt;code&amp;gt;.ebextensions&amp;lt;/code&amp;gt;, adding a &amp;lt;code&amp;gt;wsgi.authorization.config&amp;lt;/code&amp;gt; file, with the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;files:&lt;br /&gt;
    &amp;quot;/etc/httpd/conf.d/wsgiauth.conf&amp;quot;:&lt;br /&gt;
        mode: &amp;quot;000644&amp;quot;&lt;br /&gt;
        owner: root&lt;br /&gt;
        group: root&lt;br /&gt;
        content: |&lt;br /&gt;
            WSGIPassAuthorization On&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IAM Notes ==&lt;br /&gt;
&lt;br /&gt;
* you need policy AmazonRDSReadOnlyAccess for your IAM to be able to list RDS instances&lt;br /&gt;
&lt;br /&gt;
== AWS Lambda (Py) Notes ==&lt;br /&gt;
&lt;br /&gt;
For &amp;lt;tt&amp;gt;handler(event, context)&amp;lt;/tt&amp;gt; function, parameters are in:&lt;br /&gt;
&lt;br /&gt;
* GET parameters in &amp;lt;tt&amp;gt;event[&amp;quot;multiValueQueryStringParameters&amp;quot;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
** ''note'': parameters are stored in arrays, the lambda's parser correctly presumes that there may be multiple values; e.g. &amp;lt;tt&amp;gt;event[&amp;quot;multiValueQueryStringParameters&amp;quot;] = {&amp;quot;param&amp;quot;: [&amp;quot;value&amp;quot;]}&amp;lt;/tt&amp;gt;&lt;br /&gt;
* path parameters in &amp;lt;tt&amp;gt;event[&amp;quot;pathParameters&amp;quot;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
** ''note'': path parameters are specified in the SAM ''yaml'', under &amp;lt;tt&amp;gt;Path&amp;lt;/tt&amp;gt; property, as &amp;lt;tt&amp;gt;Path: /v1/user/{user_id}/data/&amp;lt;/tt&amp;gt;&lt;br /&gt;
* POST/PUT body in &amp;lt;tt&amp;gt;event[&amp;quot;body&amp;quot;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
** ''note'': stored as string, you have to &amp;lt;tt&amp;gt;json.loads()&amp;lt;/tt&amp;gt; or similar&lt;br /&gt;
&lt;br /&gt;
== boto3 Snippets ==&lt;br /&gt;
&lt;br /&gt;
=== Generate presigned S3 URL ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;s3 = boto3.client('s3', config=botocore.client.Config(signature_version='s3v4', region_name=BUCKET_REGION))&lt;br /&gt;
resp = s3.generate_presigned_url('get_object', Params={'Bucket': BUCKET, 'Key': KEY}, ExpiresIn=SECONDS)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AWS Chalice ==&lt;br /&gt;
&lt;br /&gt;
Prepare your virtualenv, and install boto3 and Chalice in it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ virtualenv ~/.virtualenvs/test-venv&lt;br /&gt;
$ source ~/.virtualenvs/test-venv/bin/activate&lt;br /&gt;
(test-venv) $ pip install boto3 chalice&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connection to RDS ===&lt;br /&gt;
&lt;br /&gt;
Lambda's are typically not restricted to VPC, while RDS is strictly tied to it.&lt;br /&gt;
You need to assign your Chalice Lambda's to the same subnets as the RDS, and the same security group.&lt;br /&gt;
Chalice does almost all of this for you!&lt;br /&gt;
&lt;br /&gt;
You just need to copy all subnet ID's used by your RDS, and the security group ID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# .chalice/config.json:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;2.0&amp;quot;,&lt;br /&gt;
  &amp;quot;app_name&amp;quot;: &amp;quot;chalice-test&amp;quot;,&lt;br /&gt;
  &amp;quot;environment_variables&amp;quot;: {&lt;br /&gt;
    &amp;quot;var&amp;quot;: &amp;quot;value&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;layers&amp;quot;: [&amp;quot;arn:aws:lambda:...&amp;quot;],&lt;br /&gt;
  &amp;quot;stages&amp;quot;: {&lt;br /&gt;
    &amp;quot;dev&amp;quot;: {&lt;br /&gt;
      &amp;quot;api_gateway_stage&amp;quot;: &amp;quot;api&amp;quot;,&lt;br /&gt;
      &amp;quot;subnet_ids&amp;quot;: [&lt;br /&gt;
        &amp;quot;subnet-...&amp;quot;, ...&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;security_group_ids&amp;quot;: [&lt;br /&gt;
        &amp;quot;sg-...&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Send and Download Binary Files ===&lt;br /&gt;
&lt;br /&gt;
There are two sides of this story, influencing both your Chalice code, and influencing the receiving code (your frontend app).&lt;br /&gt;
&lt;br /&gt;
On the Chalice side, you simply use the &amp;lt;tt&amp;gt;Response&amp;lt;/tt&amp;gt; object with some of the registered binary types. I typically just use &amp;lt;tt&amp;gt;application/octet-stream&amp;lt;/tt&amp;gt;...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@app.route('/binary-data')&lt;br /&gt;
def bin_echo():&lt;br /&gt;
    raw_request_body = app.current_request.raw_body&lt;br /&gt;
    return Response(body=binary_data,&lt;br /&gt;
                    status_code=200,&lt;br /&gt;
                    headers={'Content-Type': 'application/octet-stream'})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[https://chalice.readthedocs.io/en/latest/topics/views.html#binary-content For more info see the Chalice documentation]&lt;br /&gt;
&lt;br /&gt;
On the frontend side, you need to make sure API Gateway does not mess you up - you need to specify &amp;lt;tt&amp;gt;Accept&amp;lt;/tt&amp;gt; header of the binary type (not necessarily of the same type as the one returned from Chalice). If you specify &amp;lt;tt&amp;gt;*/*&amp;lt;/tt&amp;gt; as the accepted type, you'll receive base64 encoded data.&lt;br /&gt;
&lt;br /&gt;
== Building a Python Layer ==&lt;br /&gt;
&lt;br /&gt;
We'll be using docker Amazon Linux image.&lt;br /&gt;
&lt;br /&gt;
Below, commands starting with &amp;lt;tt&amp;gt;$&amp;lt;/tt&amp;gt; are run on your machine, while those starting with &amp;lt;tt&amp;gt;bash-4.2#&amp;lt;/tt&amp;gt; are run within the docker container.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat docker-compose.yaml &lt;br /&gt;
version: &amp;quot;3&amp;quot;&lt;br /&gt;
services:&lt;br /&gt;
  amzlinux:&lt;br /&gt;
    image: &amp;quot;amazonlinux&amp;quot;&lt;br /&gt;
    command: &amp;quot;sleep infinity&amp;quot;&lt;br /&gt;
    volumes:&lt;br /&gt;
      - ./:/host&lt;br /&gt;
&lt;br /&gt;
$ docker-compose up&lt;br /&gt;
Creating network &amp;quot;layer-example_default&amp;quot; with the default driver&lt;br /&gt;
Pulling amzlinux (amazonlinux:)...&lt;br /&gt;
[...]&lt;br /&gt;
Attaching to layer-example_amzlinux_1&lt;br /&gt;
&lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES&lt;br /&gt;
a5107c00ed35        amazonlinux         &amp;quot;sleep infinity&amp;quot;    10 seconds ago      Up 8 seconds                            '''layer-example_amzlinux_1'''&lt;br /&gt;
&lt;br /&gt;
$ docker exec -it layer-example_amzlinux_1 /bin/bash&lt;br /&gt;
&lt;br /&gt;
bash-4.2# yum -y update&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; bash-4.2# yum -y groupinstall &amp;quot;Development Tools&amp;quot;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; bash-4.2# yum -y install Cython&lt;br /&gt;
&lt;br /&gt;
bash-4.2# yum -y install python3-pip.noarch zip&lt;br /&gt;
[...]&lt;br /&gt;
Installed:&lt;br /&gt;
  python3-pip.noarch 0:9.0.3-1.amzn2.0.1&lt;br /&gt;
&lt;br /&gt;
bash-4.2# cd /host/&lt;br /&gt;
&lt;br /&gt;
bash-4.2# mkdir -p sqlalchemy-layer/python&lt;br /&gt;
&lt;br /&gt;
bash-4.2# pip3 install sqlalchemy -t sqlalchemy-layer/python/&lt;br /&gt;
[...]&lt;br /&gt;
Successfully installed sqlalchemy-1.3.11&lt;br /&gt;
&lt;br /&gt;
bash-4.2# pip3 install psycopg2-binary -t sqlalchemy-layer/python/&lt;br /&gt;
[...]&lt;br /&gt;
Successfully installed psycopg2-binary-2.8.4&lt;br /&gt;
&lt;br /&gt;
bash-4.2# cd sqlalchemy-layer/&lt;br /&gt;
bash-4.2# zip -r aws-sqlalchemy-layer.zip python/ -x \*.pyc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can upload the &amp;lt;tt&amp;gt;aws-sqlalchemy-layer.zip&amp;lt;/tt&amp;gt; as a Layer through AWS console.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-04-09T11:37:25Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* SQLAlchemy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
from typing import ContextManager&lt;br /&gt;
from sqlalchemy.orm.session import Session&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session() -&amp;gt; ContextManager[Session]:&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable&lt;br /&gt;
&lt;br /&gt;
with db_session():&lt;br /&gt;
    print(CreateTable(MyModel.__table__))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or, without actually instantiating an engine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
print(CreateTable(MyModel.__table__).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;select count(*)&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;session.query(MyModel).with_entities(func.count()).scalar()&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_PSQL</id>
		<title>Short Notes on PSQL</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_PSQL"/>
				<updated>2020-04-08T15:46:30Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: Created page with &amp;quot;PSQL aka Postgres aka PostgreSQL... I prefer psql.  == Dump and Restore ==  &amp;lt;pre&amp;gt;dump: $ pg_dump -h host -p 5432 -U user -F c -b -v -f /tmp/db_name.backup db_name restore: $ p...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;PSQL aka Postgres aka PostgreSQL... I prefer psql.&lt;br /&gt;
&lt;br /&gt;
== Dump and Restore ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;dump:&lt;br /&gt;
$ pg_dump -h host -p 5432 -U user -F c -b -v -f /tmp/db_name.backup db_name&lt;br /&gt;
restore:&lt;br /&gt;
$ pg_restore -h host -p 5432 -U user -d db_name -v /tmp/db_name.backup&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2020-04-08T15:42:36Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* PHP */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&lt;br /&gt;
$ jul () { date -d &amp;quot;$1-01-01 +$2 days -1 day&amp;quot; &amp;quot;+%Y%m%d&amp;quot;; }   - `jul $year $daynum` prints $daynum's day of $year, with Jan 1st being day 1&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
* ''convert album contained in APE or similar file with CUE into separate MP3 tracks''&lt;br /&gt;
 ffmpeg -i cd.ape -ab 256k cd.mp3&lt;br /&gt;
 mp3splt -a -c cd.cue cd.mp3&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on JS|All things JS - React, Vue, ...]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PSQL|PSQL, Postgres, PostgreSQL]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2020-04-01T12:40:59Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Bash */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&lt;br /&gt;
$ jul () { date -d &amp;quot;$1-01-01 +$2 days -1 day&amp;quot; &amp;quot;+%Y%m%d&amp;quot;; }   - `jul $year $daynum` prints $daynum's day of $year, with Jan 1st being day 1&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
* ''convert album contained in APE or similar file with CUE into separate MP3 tracks''&lt;br /&gt;
 ffmpeg -i cd.ape -ab 256k cd.mp3&lt;br /&gt;
 mp3splt -a -c cd.cue cd.mp3&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on JS|All things JS - React, Vue, ...]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2020-03-20T17:52:16Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* ffmpeg */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
* ''convert album contained in APE or similar file with CUE into separate MP3 tracks''&lt;br /&gt;
 ffmpeg -i cd.ape -ab 256k cd.mp3&lt;br /&gt;
 mp3splt -a -c cd.cue cd.mp3&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on JS|All things JS - React, Vue, ...]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-02-28T07:22:03Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Importing Files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Merging Dictionaries ==&lt;br /&gt;
&lt;br /&gt;
Below are few solutions, the first one works for any list of dictionaries, the rest is just for 2 dict's, with the last 2 suitable for inlining:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# as a generic function that merges list of dict's&lt;br /&gt;
def merge_dicts(dicts: list) -&amp;gt; dict:&lt;br /&gt;
    res = dict()&lt;br /&gt;
    for d in dicts:&lt;br /&gt;
        res.update(d)&lt;br /&gt;
    return res&lt;br /&gt;
&lt;br /&gt;
# if you're merging known number of dict's:&lt;br /&gt;
&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return dict(a, **b)&lt;br /&gt;
&lt;br /&gt;
# python 3.5+, the fastest of the lot&lt;br /&gt;
def merge_two_1(a: dict, b: dict) -&amp;gt; dict:&lt;br /&gt;
    return {**a, **b}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session():&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable&lt;br /&gt;
&lt;br /&gt;
with db_session():&lt;br /&gt;
    print(CreateTable(MyModel.__table__))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or, without actually instantiating an engine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
print(CreateTable(MyModel.__table__).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-02-14T19:29:19Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Show Create Statement for Your Model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session():&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable&lt;br /&gt;
&lt;br /&gt;
with db_session():&lt;br /&gt;
    print(CreateTable(MyModel.__table__))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or, without actually instantiating an engine:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.dialects import postgresql&lt;br /&gt;
&lt;br /&gt;
print(CreateTable(MyModel.__table__).compile(dialect=postgresql.dialect()))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-02-14T14:14:09Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* SQLAlchemy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Making Session Self-Recoverable ===&lt;br /&gt;
&lt;br /&gt;
Some DB's, most prominently Postgres, do not recover well from errors (e.g. Pg just keeps saying that there's error in current transaction).&lt;br /&gt;
One way is to rollback the transaction on &amp;quot;any&amp;quot; error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from contextlib import contextmanager&lt;br /&gt;
&lt;br /&gt;
@contextmanager&lt;br /&gt;
def db_session():&lt;br /&gt;
    session = init()    # get the session any way you like&lt;br /&gt;
    try:&lt;br /&gt;
        yield session&lt;br /&gt;
    except:&lt;br /&gt;
        session.rollback()&lt;br /&gt;
        raise&lt;br /&gt;
    else:&lt;br /&gt;
        session.commit()&lt;br /&gt;
&lt;br /&gt;
def use_db():&lt;br /&gt;
    with db_session() as session:&lt;br /&gt;
        # use session object&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Create Statement for Your Model ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;from sqlalchemy.schema import CreateTable&lt;br /&gt;
with db_session():&lt;br /&gt;
    print(CreateTable(MyModel.__table__))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_JS</id>
		<title>Short Notes on JS</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_JS"/>
				<updated>2020-02-04T15:14:11Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Fetch Patterns ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;fetch(&amp;quot;url&amp;quot;, { options... })&lt;br /&gt;
  .then((response) =&amp;gt; {&lt;br /&gt;
    if (!response.ok)&lt;br /&gt;
      throw new Error('Network response was not ok');&lt;br /&gt;
    return response.json();  // or response.blob(), etc.&lt;br /&gt;
  })&lt;br /&gt;
  .then((data) =&amp;gt; {&lt;br /&gt;
    // do something with the data received&lt;br /&gt;
  })&lt;br /&gt;
  .catch((error) =&amp;gt; {&lt;br /&gt;
    console.error('Failed to fetch:', error);&lt;br /&gt;
  });&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Environment Variables in WebPack ==&lt;br /&gt;
&lt;br /&gt;
WebPack does not have access to environment (duh), so you need to &amp;quot;bake&amp;quot; any relevant environment variables in the WebPack during build:&lt;br /&gt;
&amp;lt;pre&amp;gt;new webpack.DefinePlugin({&lt;br /&gt;
  'process.env': {&lt;br /&gt;
    NODE_ENV: JSON.stringify(process.env.NODE_ENV),&lt;br /&gt;
    STAGE: JSON.stringify(process.env.STAGE),&lt;br /&gt;
    // ...&lt;br /&gt;
  }&lt;br /&gt;
})&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging in VS Code on Linux ==&lt;br /&gt;
&lt;br /&gt;
* install ''Debugger for Chrome'' extension&lt;br /&gt;
* open the ''launch.json'' file, and edit as follows:&lt;br /&gt;
** custom profile - ''user-data-dir'' - is used, to make sure you have clean (enough) slate&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  // Use IntelliSense to learn about possible attributes.&lt;br /&gt;
  // Hover to view descriptions of existing attributes.&lt;br /&gt;
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;0.2.0&amp;quot;,&lt;br /&gt;
  &amp;quot;configurations&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;chrome&amp;quot;,&lt;br /&gt;
      &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
      &amp;quot;runtimeExecutable&amp;quot;: &amp;quot;/usr/bin/chromium-browser&amp;quot;,&lt;br /&gt;
      &amp;quot;runtimeArgs&amp;quot;: [&amp;quot;--remote-debugging-port=9222&amp;quot;, &amp;quot;--user-data-dir=/home/user/tmp/remote-profile&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Launch Chrome against localhost&amp;quot;,&lt;br /&gt;
      &amp;quot;url&amp;quot;: &amp;quot;http://localhost:3000&amp;quot;,&lt;br /&gt;
      &amp;quot;webRoot&amp;quot;: &amp;quot;${workspaceFolder}&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run the npm (the port used should correspond to the ''url'' key above)&lt;br /&gt;
* hit debug in VS Code, add breakpoints, etc., and enjoy!&lt;br /&gt;
** this will actually open new browser window, as subwindow of VS Code, neat!&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_JS</id>
		<title>Short Notes on JS</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_JS"/>
				<updated>2020-01-28T11:50:57Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Fetch Patterns ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;fetch(&amp;quot;url&amp;quot;, { options... })&lt;br /&gt;
  .then((response) =&amp;gt; {&lt;br /&gt;
    if (!response.ok)&lt;br /&gt;
      throw new Error('Network response was not ok');&lt;br /&gt;
    return response.json();  // or response.blob(), etc.&lt;br /&gt;
  })&lt;br /&gt;
  .then((data) =&amp;gt; {&lt;br /&gt;
    // do something with the data received&lt;br /&gt;
  })&lt;br /&gt;
  .catch((error) =&amp;gt; {&lt;br /&gt;
    console.error('Failed to fetch:', error);&lt;br /&gt;
  });&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Environment Variables in WebPack ==&lt;br /&gt;
&lt;br /&gt;
WebPack does not have access to environment (duh), so you need to &amp;quot;bake&amp;quot; any relevant environment variables in the WebPack during build:&lt;br /&gt;
&amp;lt;pre&amp;gt;new webpack.DefinePlugin({&lt;br /&gt;
  'process.env': {&lt;br /&gt;
    NODE_ENV: JSON.stringify(process.env.NODE_ENV),&lt;br /&gt;
    STAGE: JSON.stringify(process.env.STAGE),&lt;br /&gt;
    // ...&lt;br /&gt;
  }&lt;br /&gt;
})&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_JS</id>
		<title>Short Notes on JS</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_JS"/>
				<updated>2020-01-24T12:21:35Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: Created page with &amp;quot;== Fetch Patterns ==  &amp;lt;pre&amp;gt;fetch(&amp;quot;url&amp;quot;, { options... })   .then((response) =&amp;gt; {     if (!response.ok)       throw new Error('Network response was not ok');     return response...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Fetch Patterns ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;fetch(&amp;quot;url&amp;quot;, { options... })&lt;br /&gt;
  .then((response) =&amp;gt; {&lt;br /&gt;
    if (!response.ok)&lt;br /&gt;
      throw new Error('Network response was not ok');&lt;br /&gt;
    return response.json();  // or response.blob(), etc.&lt;br /&gt;
  })&lt;br /&gt;
  .then((data) =&amp;gt; {&lt;br /&gt;
    // do something with the data received&lt;br /&gt;
  })&lt;br /&gt;
  .catch((error) =&amp;gt; {&lt;br /&gt;
    console.error('Failed to fetch:', error);&lt;br /&gt;
  });&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2020-01-24T12:12:42Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* git */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on JS|All things JS - React, Vue, ...]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2020-01-06T08:40:35Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* AWS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
* Notes on IAM&lt;br /&gt;
* AWS Lambda with Python - Notes&lt;br /&gt;
* boto3 Snippets&lt;br /&gt;
* AWS Chalice&lt;br /&gt;
* Building a Python Layer&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2020-01-01T19:33:39Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* SQLAlchemy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = ['{} ({})'.format(col['name'], col['type']) for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(table_name, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2019-12-28T12:27:14Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Ubuntu / Debian / Gnome etc. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
* increase number of inotify watchers&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
8192&lt;br /&gt;
$ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf&lt;br /&gt;
$ sudo sysctl -p&lt;br /&gt;
$ cat /proc/sys/fs/inotify/max_user_watches &lt;br /&gt;
524288&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2019-12-28T11:32:57Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* SQLAlchemy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Tables and Their Columns ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;import sqlalchemy as sqla&lt;br /&gt;
&lt;br /&gt;
db_conn_str = &amp;quot;..your connection string..&amp;quot;&lt;br /&gt;
engine = sqla.create_engine(db_conn_str)&lt;br /&gt;
inspector = sqla.inspect(engine)&lt;br /&gt;
schemas = inspector.get_schema_names()&lt;br /&gt;
&lt;br /&gt;
for schema in schemas:&lt;br /&gt;
    print(&amp;quot;schema: {}&amp;quot;.format(schema))&lt;br /&gt;
    for table_name in inspector.get_table_names(schema=schema):&lt;br /&gt;
        cols = [col for col in inspector.get_columns(table_name, schema=schema)]&lt;br /&gt;
        print(&amp;quot;Table: {} ({})&amp;quot;.format(schema, ', '.join(cols)))&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_git</id>
		<title>Short Notes on git</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_git"/>
				<updated>2019-12-27T16:35:43Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Basic Commands ==&lt;br /&gt;
&lt;br /&gt;
The ''git'' has 3 &amp;quot;trees&amp;quot; maintained automatically within your local repo - &amp;quot;working copy&amp;quot; is the files you're actually working on, &amp;quot;index&amp;quot; is kind of staging area, and &amp;quot;head&amp;quot; is your last actual commit.&lt;br /&gt;
You're working on your ''working copy'', then add changes to the ''index'', then push those to ''head'' locally, and finally push those to (remote) repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# two ways to check out a repo; 1) first local, then connect&lt;br /&gt;
$ git init                                   # init local copy&lt;br /&gt;
$ git remote add origin &amp;lt;server&amp;gt;             # connect it to remote&lt;br /&gt;
# or, 2) checkout a remote repo straight away&lt;br /&gt;
$ git clone /path/to/repo                    # create working copy of local repo&lt;br /&gt;
$ git clone user@host:/path/to/repo          # create working copy of remote repo&lt;br /&gt;
&lt;br /&gt;
$ git status                                 # get info about local copy, incl. branch ID, changes, etc.&lt;br /&gt;
&lt;br /&gt;
$ git fetch                                  # download changes but do not integrate in the HEAD&lt;br /&gt;
$ git pull                                   # update the local copy to the latest revision&lt;br /&gt;
$ git pull &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # pull specific branch&lt;br /&gt;
$ git diff &amp;lt;source&amp;gt; &amp;lt;dest&amp;gt;                   # view differences between &amp;quot;source&amp;quot; and &amp;quot;dest&amp;quot; branches&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                         # merge changes from another branch (e.g. &amp;quot;origin/master&amp;quot;)&lt;br /&gt;
                                             # you should merge from remote (&amp;quot;origin&amp;quot;) as your local copy may differ&lt;br /&gt;
&lt;br /&gt;
# set meld as diff and merge tool; use --global to apply globally, not just per-repo&lt;br /&gt;
$ git config difftool meld&lt;br /&gt;
$ git config difftool.prompt false           # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool meld                  # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool.prompt false&lt;br /&gt;
$ git difftool                               # you need to use &amp;quot;difftool&amp;quot; to run meld for diff, not just `git diff`&lt;br /&gt;
$ git mergetool                              # run this only after `git merge` if there are any conflicts to be resolved&lt;br /&gt;
&lt;br /&gt;
# getting the changes to the remote repo&lt;br /&gt;
$ git add [-i] &amp;lt;file&amp;gt;                        # add changes from file(s) to index (-i = interactive)&lt;br /&gt;
$ git commit -m 'message'                    # commit changes from index to head&lt;br /&gt;
$ git push origin master                     # push changes from head to master branch, or&lt;br /&gt;
$ git push &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # push changes to &amp;lt;branch&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ git checkout -- &amp;lt;file&amp;gt;                     # revert file and replace with current HEAD version, exc. of changes added to Index&lt;br /&gt;
$ git fetch origin                           # fetch latest history from server&lt;br /&gt;
$ git reset --hard origin/master             # drop all local changes, incl. those in Index&lt;br /&gt;
&lt;br /&gt;
# branching&lt;br /&gt;
$ git branch -av                             # list existing branches&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                   # create a new branch, and switch to it, or&lt;br /&gt;
$ git checkout &amp;lt;branch&amp;gt;                      # switch to branch (make it your HEAD)&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt; --set-upstream    # make the branch available to others, and set the upstream&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                     # delete local branch&lt;br /&gt;
$ git branch -dr &amp;lt;remote/branch&amp;gt;             # delete remote branch&lt;br /&gt;
&lt;br /&gt;
# other stuff&lt;br /&gt;
$ git tag &amp;lt;tag name&amp;gt; &amp;lt;commit id&amp;gt;             # create tag from a commit&lt;br /&gt;
$ git log --pretty=oneline [--author=&amp;lt;name&amp;gt;] # one-line per commit listing&lt;br /&gt;
$ git log --graph --oneline --decorate --all # ascii tree of branches, tags, ...&lt;br /&gt;
$ git log --name-status                      # list changed files&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;svn:externals&amp;quot; like inclusion of another repo; need to commit this as well&lt;br /&gt;
$ git submodule add -b &amp;lt;branch&amp;gt; &amp;lt;repo&amp;gt; [&amp;lt;folder&amp;gt;]&lt;br /&gt;
$ git add &amp;lt;folder&amp;gt; .gitmodules ; + commit ; + push&lt;br /&gt;
&lt;br /&gt;
$ git submodule update --remote              # update the submodules from their respective repo's&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Typical Flow ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git clone [remote repo]                     # get a local copy of the repo&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                    # start a new branch&lt;br /&gt;
&lt;br /&gt;
# do your changes...&lt;br /&gt;
$ git add &amp;lt;files&amp;gt;                             # register changes for commit&lt;br /&gt;
$ git commit -m 'message'&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt;                    # commit the branch with changes to repo&lt;br /&gt;
# repeat as needed...&lt;br /&gt;
&lt;br /&gt;
# once done with the branch&lt;br /&gt;
$ git merge master                            # pull all changes from &amp;quot;master&amp;quot;&lt;br /&gt;
$ git mergetool                               # resolve conflicts; commit again to branch if needed - `add`, `commit`, `push`&lt;br /&gt;
$ git checkout master                         # switch to master&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                          # this should pass ok; commit to &amp;quot;master&amp;quot; afterwards&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                      # clean up - remove the branch&lt;br /&gt;
$ git tag &amp;lt;tag&amp;gt; &amp;lt;commit id&amp;gt;                   # optionally, also tag the commit after merging&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resolve Conflict ===&lt;br /&gt;
&lt;br /&gt;
If on &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; you get a message:&lt;br /&gt;
&amp;lt;pre&amp;gt;error: Your local changes to the following files would be overwritten by merge:&lt;br /&gt;
	[list of files]&lt;br /&gt;
Please, commit your changes or stash them before you can merge.&lt;br /&gt;
Aborting&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to resolve the conflict manually.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git fetch&lt;br /&gt;
git add [file]&lt;br /&gt;
git commit -m 'resolving'&lt;br /&gt;
git merge&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At which point you'll get message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Auto-merging [files]&lt;br /&gt;
CONFLICT (content): Merge conflict in [files]&lt;br /&gt;
Automatic merge failed; fix conflicts and then commit the result.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you need to manually edit the file(s) to resolve the conflict, and then &amp;lt;tt&amp;gt;add/commit&amp;lt;/tt&amp;gt; the resolved file(s).&lt;br /&gt;
&lt;br /&gt;
=== Skip Retyping Your Password ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git config --global credential.helper store&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; and enter your username and password. These will be stored in &amp;lt;tt&amp;gt;~/.git-credentials&amp;lt;/tt&amp;gt; file and reused each time.&lt;br /&gt;
&lt;br /&gt;
=== Ignoring Files and Folders ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ touch .gitignore&lt;br /&gt;
# edit the file with your fave editor (folders should end with '/'):&lt;br /&gt;
folder/&lt;br /&gt;
file.txt&lt;br /&gt;
&lt;br /&gt;
# it's good practice to commit the file as well&lt;br /&gt;
$ git add .gitignore&lt;br /&gt;
$ git commit -m &amp;quot;Added .gitignore file&amp;quot;&lt;br /&gt;
$ git push origin master&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_git</id>
		<title>Short Notes on git</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_git"/>
				<updated>2019-12-27T16:34:02Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Skip Retyping Your Password */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Basic Commands ==&lt;br /&gt;
&lt;br /&gt;
The ''git'' has 3 &amp;quot;trees&amp;quot; maintained automatically within your local repo - &amp;quot;working copy&amp;quot; is the files you're actually working on, &amp;quot;index&amp;quot; is kind of staging area, and &amp;quot;head&amp;quot; is your last actual commit.&lt;br /&gt;
You're working on your ''working copy'', then add changes to the ''index'', then push those to ''head'' locally, and finally push those to (remote) repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# two ways to check out a repo; 1) first local, then connect&lt;br /&gt;
$ git init                                   # init local copy&lt;br /&gt;
$ git remote add origin &amp;lt;server&amp;gt;             # connect it to remote&lt;br /&gt;
# or, 2) checkout a remote repo straight away&lt;br /&gt;
$ git clone /path/to/repo                    # create working copy of local repo&lt;br /&gt;
$ git clone user@host:/path/to/repo          # create working copy of remote repo&lt;br /&gt;
&lt;br /&gt;
$ git status                                 # get info about local copy, incl. branch ID, changes, etc.&lt;br /&gt;
&lt;br /&gt;
$ git fetch                                  # download changes but do not integrate in the HEAD&lt;br /&gt;
$ git pull                                   # update the local copy to the latest revision&lt;br /&gt;
$ git pull &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # pull specific branch&lt;br /&gt;
$ git diff &amp;lt;source&amp;gt; &amp;lt;dest&amp;gt;                   # view differences between &amp;quot;source&amp;quot; and &amp;quot;dest&amp;quot; branches&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                         # merge changes from another branch (e.g. &amp;quot;origin/master&amp;quot;)&lt;br /&gt;
                                             # you should merge from remote (&amp;quot;origin&amp;quot;) as your local copy may differ&lt;br /&gt;
&lt;br /&gt;
# set meld as diff and merge tool; use --global to apply globally, not just per-repo&lt;br /&gt;
$ git config difftool meld&lt;br /&gt;
$ git config difftool.prompt false           # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool meld                  # don't ask each time whether to run meld&lt;br /&gt;
$ git config mergetool.prompt false&lt;br /&gt;
$ git difftool                               # you need to use &amp;quot;difftool&amp;quot; to run meld for diff, not just `git diff`&lt;br /&gt;
$ git mergetool                              # run this only after `git merge` if there are any conflicts to be resolved&lt;br /&gt;
&lt;br /&gt;
# getting the changes to the remote repo&lt;br /&gt;
$ git add [-i] &amp;lt;file&amp;gt;                        # add changes from file(s) to index (-i = interactive)&lt;br /&gt;
$ git commit -m 'message'                    # commit changes from index to head&lt;br /&gt;
$ git push origin master                     # push changes from head to master branch, or&lt;br /&gt;
$ git push &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;                 # push changes to &amp;lt;branch&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$ git checkout -- &amp;lt;file&amp;gt;                     # revert file and replace with current HEAD version, exc. of changes added to Index&lt;br /&gt;
$ git fetch origin                           # fetch latest history from server&lt;br /&gt;
$ git reset --hard origin/master             # drop all local changes, incl. those in Index&lt;br /&gt;
&lt;br /&gt;
# branching&lt;br /&gt;
$ git branch -av                             # list existing branches&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                   # create a new branch, and switch to it, or&lt;br /&gt;
$ git checkout &amp;lt;branch&amp;gt;                      # switch to branch (make it your HEAD)&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt; --set-upstream    # make the branch available to others, and set the upstream&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                     # delete local branch&lt;br /&gt;
$ git branch -dr &amp;lt;remote/branch&amp;gt;             # delete remote branch&lt;br /&gt;
&lt;br /&gt;
# other stuff&lt;br /&gt;
$ git tag &amp;lt;tag name&amp;gt; &amp;lt;commit id&amp;gt;             # create tag from a commit&lt;br /&gt;
$ git log --pretty=oneline [--author=&amp;lt;name&amp;gt;] # one-line per commit listing&lt;br /&gt;
$ git log --graph --oneline --decorate --all # ascii tree of branches, tags, ...&lt;br /&gt;
$ git log --name-status                      # list changed files&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;svn:externals&amp;quot; like inclusion of another repo; need to commit this as well&lt;br /&gt;
$ git submodule add -b &amp;lt;branch&amp;gt; &amp;lt;repo&amp;gt; [&amp;lt;folder&amp;gt;]&lt;br /&gt;
$ git add &amp;lt;folder&amp;gt; .gitmodules ; + commit ; + push&lt;br /&gt;
&lt;br /&gt;
$ git submodule update --remote              # update the submodules from their respective repo's&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Typical Flow ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git clone [remote repo]                     # get a local copy of the repo&lt;br /&gt;
$ git checkout -b &amp;lt;branch&amp;gt;                    # start a new branch&lt;br /&gt;
&lt;br /&gt;
# do your changes...&lt;br /&gt;
$ git add &amp;lt;files&amp;gt;                             # register changes for commit&lt;br /&gt;
$ git commit -m 'message'&lt;br /&gt;
$ git push origin &amp;lt;branch&amp;gt;                    # commit the branch with changes to repo&lt;br /&gt;
# repeat as needed...&lt;br /&gt;
&lt;br /&gt;
# once done with the branch&lt;br /&gt;
$ git merge master                            # pull all changes from &amp;quot;master&amp;quot;&lt;br /&gt;
$ git mergetool                               # resolve conflicts; commit again to branch if needed - `add`, `commit`, `push`&lt;br /&gt;
$ git checkout master                         # switch to master&lt;br /&gt;
$ git merge &amp;lt;branch&amp;gt;                          # this should pass ok; commit to &amp;quot;master&amp;quot; afterwards&lt;br /&gt;
$ git branch -d &amp;lt;branch&amp;gt;                      # clean up - remove the branch&lt;br /&gt;
$ git tag &amp;lt;tag&amp;gt; &amp;lt;commit id&amp;gt;                   # optionally, also tag the commit after merging&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resolve Conflict ===&lt;br /&gt;
&lt;br /&gt;
If on &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; you get a message:&lt;br /&gt;
&amp;lt;pre&amp;gt;error: Your local changes to the following files would be overwritten by merge:&lt;br /&gt;
	[list of files]&lt;br /&gt;
Please, commit your changes or stash them before you can merge.&lt;br /&gt;
Aborting&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You need to resolve the conflict manually.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git fetch&lt;br /&gt;
git add [file]&lt;br /&gt;
git commit -m 'resolving'&lt;br /&gt;
git merge&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At which point you'll get message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Auto-merging [files]&lt;br /&gt;
CONFLICT (content): Merge conflict in [files]&lt;br /&gt;
Automatic merge failed; fix conflicts and then commit the result.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you need to manually edit the file(s) to resolve the conflict, and then &amp;lt;tt&amp;gt;add/commit&amp;lt;/tt&amp;gt; the resolved file(s).&lt;br /&gt;
&lt;br /&gt;
=== Skip Retyping Your Password ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ git config --global credential.helper store&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run &amp;lt;tt&amp;gt;git pull&amp;lt;/tt&amp;gt; and enter your username and password. These will be stored in &amp;lt;tt&amp;gt;~/.git-credentials&amp;lt;/tt&amp;gt; file and reused each time.&lt;br /&gt;
&lt;br /&gt;
=== Ignoring Files and Folders ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ touch .gitignore&lt;br /&gt;
# edit the file with your fave editor (folders should end with '/'):&lt;br /&gt;
folder/&lt;br /&gt;
file.txt&lt;br /&gt;
&lt;br /&gt;
# it's good practice to commit the file as well&lt;br /&gt;
$ git add .gitignore&lt;br /&gt;
$ git commit -m &amp;quot;Added .gitignore file&amp;quot;&lt;br /&gt;
$ git push origin master&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using Git with gnome-keyring ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install libgnome-keyring-dev&lt;br /&gt;
cd /usr/share/doc/git/contrib/credential/gnome-keyring&lt;br /&gt;
sudo make&lt;br /&gt;
git config --global credential.helper /usr/share/doc/git/contrib/credential/gnome-keyring/git-credential-gnome-keyring&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2019-12-27T16:09:25Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Ubuntu / Debian / Gnome etc. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Up-to-Date Versions of Packages ====&lt;br /&gt;
&lt;br /&gt;
* '''Python'''&lt;br /&gt;
Ubuntu 18.04 ships with Python 3.6, but Amazon Linux uses 3.7, so e.g. to use and build Lambda layers and match those against packages you deploy, you need to install 3.7:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo add-apt-repository ppa:deadsnakes/ppa&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install python3.7&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since these do not override default &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; links (and better not!), you should create corresponding venv's as:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ python3.7 -m venv [env-dir]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''NPM, node.js, etc.'''&lt;br /&gt;
The default &amp;lt;tt&amp;gt;apt&amp;lt;/tt&amp;gt; ''npm'' version is awfully outdated.&lt;br /&gt;
&lt;br /&gt;
Add NodeSource APT repo; for other versions, e.g. 12.x, change to &amp;lt;tt&amp;gt;setup_12.x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -&lt;br /&gt;
$ sudo apt update&lt;br /&gt;
$ sudo apt install nodejs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_AWS</id>
		<title>Short Notes on AWS</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_AWS"/>
				<updated>2019-12-26T14:03:41Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Building a Python Layer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Can't connect to EC2 instance ==&lt;br /&gt;
&lt;br /&gt;
The obvious 2 problems with incoming requests, that are outside of AWS's scope:&lt;br /&gt;
* check the instance's firewall&lt;br /&gt;
* check that the app is listening to all incoming (0.0.0.0/0 or your IP, not just 127.0.0.1)&lt;br /&gt;
&lt;br /&gt;
On the AWS side, check the following:&lt;br /&gt;
* make sure the Elastic IP is associated with the instance&lt;br /&gt;
** find the instance in the EC2 &amp;gt; Instances&lt;br /&gt;
** look under Description tab, Elastic IP&lt;br /&gt;
** if it's not, go to EC2 &amp;gt; Elastic IPs&lt;br /&gt;
** choose Elastic IP from the list (or, allocate new on) that is not associated with any instance&lt;br /&gt;
** choose Actions &amp;gt; Associate address, and associate it with the instance&lt;br /&gt;
* make sure Security group permissions allow the connection&lt;br /&gt;
** go to EC2 &amp;gt; Security Groups&lt;br /&gt;
** select the security group (you can find which security group instance is in in the list on EC2 &amp;gt; Instances page, last column)&lt;br /&gt;
** on the Inbound tab, check that your protocol is enabled for Source 0.0.0.0/0 (or from your IP)&lt;br /&gt;
* make sure your Internet Gateway is connected to your VPC&lt;br /&gt;
** make sure the Internet Gateway is attached to your VPC, under VPC &amp;gt; Internet Gateways &amp;gt; Summary tab&lt;br /&gt;
** go to VPC &amp;gt; Route Tables, select route table for your VPC&lt;br /&gt;
** under Routes tab, make sure that route with destination 0.0.0.0/0, with Target being your internet gateway, exists and is Active&lt;br /&gt;
&lt;br /&gt;
== Authorization header being removed by ElasticBeanstalk ==&lt;br /&gt;
&lt;br /&gt;
By default, AWS ElasticBeanstalk's WSGI server strips &amp;lt;code&amp;gt;Authorization&amp;lt;/code&amp;gt; header from requests.&lt;br /&gt;
&lt;br /&gt;
To get these back, just plug your wsgi config file through &amp;lt;code&amp;gt;.ebextensions&amp;lt;/code&amp;gt;, adding a &amp;lt;code&amp;gt;wsgi.authorization.config&amp;lt;/code&amp;gt; file, with the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;files:&lt;br /&gt;
    &amp;quot;/etc/httpd/conf.d/wsgiauth.conf&amp;quot;:&lt;br /&gt;
        mode: &amp;quot;000644&amp;quot;&lt;br /&gt;
        owner: root&lt;br /&gt;
        group: root&lt;br /&gt;
        content: |&lt;br /&gt;
            WSGIPassAuthorization On&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IAM Notes ==&lt;br /&gt;
&lt;br /&gt;
* you need policy AmazonRDSReadOnlyAccess for your IAM to be able to list RDS instances&lt;br /&gt;
&lt;br /&gt;
== AWS Lambda (Py) Notes ==&lt;br /&gt;
&lt;br /&gt;
For &amp;lt;tt&amp;gt;handler(event, context)&amp;lt;/tt&amp;gt; function, parameters are in:&lt;br /&gt;
&lt;br /&gt;
* GET parameters in &amp;lt;tt&amp;gt;event[&amp;quot;multiValueQueryStringParameters&amp;quot;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
** ''note'': parameters are stored in arrays, the lambda's parser correctly presumes that there may be multiple values; e.g. &amp;lt;tt&amp;gt;event[&amp;quot;multiValueQueryStringParameters&amp;quot;] = {&amp;quot;param&amp;quot;: [&amp;quot;value&amp;quot;]}&amp;lt;/tt&amp;gt;&lt;br /&gt;
* path parameters in &amp;lt;tt&amp;gt;event[&amp;quot;pathParameters&amp;quot;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
** ''note'': path parameters are specified in the SAM ''yaml'', under &amp;lt;tt&amp;gt;Path&amp;lt;/tt&amp;gt; property, as &amp;lt;tt&amp;gt;Path: /v1/user/{user_id}/data/&amp;lt;/tt&amp;gt;&lt;br /&gt;
* POST/PUT body in &amp;lt;tt&amp;gt;event[&amp;quot;body&amp;quot;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
** ''note'': stored as string, you have to &amp;lt;tt&amp;gt;json.loads()&amp;lt;/tt&amp;gt; or similar&lt;br /&gt;
&lt;br /&gt;
== boto3 Snippets ==&lt;br /&gt;
&lt;br /&gt;
=== Generate presigned S3 URL ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;s3 = boto3.client('s3', config=botocore.client.Config(signature_version='s3v4', region_name=BUCKET_REGION))&lt;br /&gt;
resp = s3.generate_presigned_url('get_object', Params={'Bucket': BUCKET, 'Key': KEY}, ExpiresIn=SECONDS)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== AWS Chalice ==&lt;br /&gt;
&lt;br /&gt;
Prepare your virtualenv, and install boto3 and Chalice in it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ virtualenv ~/.virtualenvs/test-venv&lt;br /&gt;
$ source ~/.virtualenvs/test-venv/bin/activate&lt;br /&gt;
(test-venv) $ pip install boto3 chalice&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Connection to RDS ===&lt;br /&gt;
&lt;br /&gt;
Lambda's are typically not restricted to VPC, while RDS is strictly tied to it.&lt;br /&gt;
You need to assign your Chalice Lambda's to the same subnets as the RDS, and the same security group.&lt;br /&gt;
Chalice does almost all of this for you!&lt;br /&gt;
&lt;br /&gt;
You just need to copy all subnet ID's used by your RDS, and the security group ID.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# .chalice/config.json:&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;version&amp;quot;: &amp;quot;2.0&amp;quot;,&lt;br /&gt;
  &amp;quot;app_name&amp;quot;: &amp;quot;chalice-test&amp;quot;,&lt;br /&gt;
  &amp;quot;environment_variables&amp;quot;: {&lt;br /&gt;
    &amp;quot;var&amp;quot;: &amp;quot;value&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;layers&amp;quot;: [&amp;quot;arn:aws:lambda:...&amp;quot;],&lt;br /&gt;
  &amp;quot;stages&amp;quot;: {&lt;br /&gt;
    &amp;quot;dev&amp;quot;: {&lt;br /&gt;
      &amp;quot;api_gateway_stage&amp;quot;: &amp;quot;api&amp;quot;,&lt;br /&gt;
      &amp;quot;subnet_ids&amp;quot;: [&lt;br /&gt;
        &amp;quot;subnet-...&amp;quot;, ...&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;security_group_ids&amp;quot;: [&lt;br /&gt;
        &amp;quot;sg-...&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Building a Python Layer ==&lt;br /&gt;
&lt;br /&gt;
We'll be using docker Amazon Linux image.&lt;br /&gt;
&lt;br /&gt;
Below, commands starting with &amp;lt;tt&amp;gt;$&amp;lt;/tt&amp;gt; are run on your machine, while those starting with &amp;lt;tt&amp;gt;bash-4.2#&amp;lt;/tt&amp;gt; are run within the docker container.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ cat docker-compose.yaml &lt;br /&gt;
version: &amp;quot;3&amp;quot;&lt;br /&gt;
services:&lt;br /&gt;
  amzlinux:&lt;br /&gt;
    image: &amp;quot;amazonlinux&amp;quot;&lt;br /&gt;
    command: &amp;quot;sleep infinity&amp;quot;&lt;br /&gt;
    volumes:&lt;br /&gt;
      - ./:/host&lt;br /&gt;
&lt;br /&gt;
$ docker-compose up&lt;br /&gt;
Creating network &amp;quot;layer-example_default&amp;quot; with the default driver&lt;br /&gt;
Pulling amzlinux (amazonlinux:)...&lt;br /&gt;
[...]&lt;br /&gt;
Attaching to layer-example_amzlinux_1&lt;br /&gt;
&lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES&lt;br /&gt;
a5107c00ed35        amazonlinux         &amp;quot;sleep infinity&amp;quot;    10 seconds ago      Up 8 seconds                            '''layer-example_amzlinux_1'''&lt;br /&gt;
&lt;br /&gt;
$ docker exec -it layer-example_amzlinux_1 /bin/bash&lt;br /&gt;
&lt;br /&gt;
bash-4.2# yum -y update&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; bash-4.2# yum -y groupinstall &amp;quot;Development Tools&amp;quot;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; bash-4.2# yum -y install Cython&lt;br /&gt;
&lt;br /&gt;
bash-4.2# yum -y install python3-pip.noarch zip&lt;br /&gt;
[...]&lt;br /&gt;
Installed:&lt;br /&gt;
  python3-pip.noarch 0:9.0.3-1.amzn2.0.1&lt;br /&gt;
&lt;br /&gt;
bash-4.2# cd /host/&lt;br /&gt;
&lt;br /&gt;
bash-4.2# mkdir -p sqlalchemy-layer/python&lt;br /&gt;
&lt;br /&gt;
bash-4.2# pip3 install sqlalchemy -t sqlalchemy-layer/python/&lt;br /&gt;
[...]&lt;br /&gt;
Successfully installed sqlalchemy-1.3.11&lt;br /&gt;
&lt;br /&gt;
bash-4.2# pip3 install psycopg2-binary -t sqlalchemy-layer/python/&lt;br /&gt;
[...]&lt;br /&gt;
Successfully installed psycopg2-binary-2.8.4&lt;br /&gt;
&lt;br /&gt;
bash-4.2# cd sqlalchemy-layer/&lt;br /&gt;
bash-4.2# zip -r aws-sqlalchemy-layer.zip python/ -x \*.pyc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can upload the &amp;lt;tt&amp;gt;aws-sqlalchemy-layer.zip&amp;lt;/tt&amp;gt; as a Layer through AWS console.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Small_Docker_Notes</id>
		<title>Small Docker Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Small_Docker_Notes"/>
				<updated>2019-12-26T12:54:48Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note - ''vm'' and ''container'' is used below interchangeably.&lt;br /&gt;
&lt;br /&gt;
== Installation and Verification ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  # install Docker&lt;br /&gt;
$ curl -fsSL https://get.docker.com/ | sh&lt;br /&gt;
&lt;br /&gt;
  # add your-user to docker group to be able to run docker as non-root&lt;br /&gt;
$ usermod -aG docker your-user&lt;br /&gt;
  # you'll need to log out and in after this, or run all docker commands as root&lt;br /&gt;
&lt;br /&gt;
  # verify the installation&lt;br /&gt;
$ docker run hello-world&lt;br /&gt;
  # this should download image from docker hub, and print &amp;quot;Hello from Docker.&amp;quot; message&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a rule of thumb: &amp;lt;tt&amp;gt;`docker`&amp;lt;/tt&amp;gt; is the &amp;quot;super-system&amp;quot; used to manage docker containers (and more). &amp;lt;tt&amp;gt;`docker-compose`&amp;lt;/tt&amp;gt; does the same tasks as ''docker'', but only on containers defined in ''docker-compose.yml'' file in current directory. So, &amp;lt;tt&amp;gt;`docker ps -a`&amp;lt;/tt&amp;gt; will list all containers, &amp;lt;tt&amp;gt;`docker-compose ps`&amp;lt;/tt&amp;gt; will list info about all containers from local ''docker-compose.yml'' file.&lt;br /&gt;
&lt;br /&gt;
If something goes wrong, check&lt;br /&gt;
 $ docker-compose logs&lt;br /&gt;
or&lt;br /&gt;
 $ docker logs ''container-id''&lt;br /&gt;
&lt;br /&gt;
== Stack in Separate Containers ==&lt;br /&gt;
&lt;br /&gt;
Let's create few containers to hold different parts of the stack:&lt;br /&gt;
* nginx&lt;br /&gt;
* php-fpm&lt;br /&gt;
* mysql&lt;br /&gt;
* data volume for mysql&lt;br /&gt;
* kyoto tycoon with python&lt;br /&gt;
* data volume for kyoto tycoon&lt;br /&gt;
&lt;br /&gt;
First, create config file for docker compose, called ''docker-compose.yml'' .&lt;br /&gt;
&amp;lt;pre&amp;gt;nginx:&lt;br /&gt;
    # based on latest nginx image&lt;br /&gt;
    image: nginx:latest&lt;br /&gt;
    ports:&lt;br /&gt;
        # map vm's port 80 to local port 8080&lt;br /&gt;
        - 8080:80&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have defined our first image, let's get it running:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ docker-compose up -d&lt;br /&gt;
&lt;br /&gt;
  # you should be able to reach the nginx on localhost:8080 now;&lt;br /&gt;
  # you can always check running containers, incl. ports map, with&lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                           NAMES&lt;br /&gt;
e795e45c3e6b        nginx:latest        &amp;quot;nginx -g 'daemon off&amp;quot;   24 hours ago        Up 24 hours         443/tcp, 0.0.0.0:8080-&amp;gt;80/tcp   dockertut_nginx_1&lt;br /&gt;
&lt;br /&gt;
  # using container ID or name from `docker ps`, you can get lots of useful info with&lt;br /&gt;
$ docker inspect {container-id|name}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding php-fpm ===&lt;br /&gt;
&lt;br /&gt;
Let's now add VM for php-fpm, and edit the ''docker-compose.yml'' like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;nginx:&lt;br /&gt;
    build:&lt;br /&gt;
        # don't use image, build based on ./docker/nginx/Dockerfile&lt;br /&gt;
        ./docker/nginx/&lt;br /&gt;
    ports:&lt;br /&gt;
        # vm's port 80 will be available as 8080 on localhost&lt;br /&gt;
        - 8080:80&lt;br /&gt;
    links:&lt;br /&gt;
        # has access to 'php' vm&lt;br /&gt;
        - php&lt;br /&gt;
    volumes:&lt;br /&gt;
        # mount current directory as /var/www/html inside the container&lt;br /&gt;
        - .:/var/www/html&lt;br /&gt;
&lt;br /&gt;
php:&lt;br /&gt;
    image: php:5.5-fpm&lt;br /&gt;
    expose:&lt;br /&gt;
        # expose port 9000 only to other vm's, not host machine like the 'ports' command&lt;br /&gt;
        - 9000&lt;br /&gt;
    volumes:&lt;br /&gt;
        - .:/var/www/html&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the nginx image is based on ''Dockerfile'' in ''./docker/nginx/'' folder, which should look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;FROM nginx:latest&lt;br /&gt;
COPY ./default.conf /etc/nginx/conf.d/default.conf&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [https://docs.docker.com/engine/reference/builder/ official Dockerfile reference] for details.&lt;br /&gt;
&lt;br /&gt;
This will build vm from ''nginx:latest'' image, and copy ''./docker/nginx/default.conf'' to ''/etc/nginx/conf.d/'' in the vm. Create this file with the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80 default_server;&lt;br /&gt;
    root /var/www/html;&lt;br /&gt;
    index index.html index.php;&lt;br /&gt;
&lt;br /&gt;
    charset utf-8;&lt;br /&gt;
&lt;br /&gt;
    location / {&lt;br /&gt;
        try_files $uri $uri/ /index.php?$query_string;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    location = /favicon.ico { access_log off; log_not_found off; }&lt;br /&gt;
    location = /robots.txt  { access_log off; log_not_found off; }&lt;br /&gt;
&lt;br /&gt;
    access_log off;&lt;br /&gt;
    error_log  /var/log/nginx/error.log error;&lt;br /&gt;
&lt;br /&gt;
    sendfile off;&lt;br /&gt;
&lt;br /&gt;
    client_max_body_size 100m;&lt;br /&gt;
&lt;br /&gt;
    location ~ \.php$ {&lt;br /&gt;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;&lt;br /&gt;
        fastcgi_pass php:9000;&lt;br /&gt;
        fastcgi_index index.php;&lt;br /&gt;
        include fastcgi_params;&lt;br /&gt;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;&lt;br /&gt;
        fastcgi_intercept_errors off;&lt;br /&gt;
        fastcgi_buffer_size 16k;&lt;br /&gt;
        fastcgi_buffers 4 16k;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    location ~ /\.ht {&lt;br /&gt;
        deny all;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;tt&amp;gt;root /var/www/html;&amp;lt;/tt&amp;gt; will actually use the mount of our local directory.&lt;br /&gt;
&lt;br /&gt;
Also note &amp;lt;tt&amp;gt;fastcgi_pass php:9000;&amp;lt;/tt&amp;gt; that uses the link created using ''links:'' key in the ''docker-compose.yml''.&lt;br /&gt;
&lt;br /&gt;
Now, let's just add ''index.php'' in the root folder (where ''docker-compose.yml'' resides):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;&lt;br /&gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;title&amp;gt;Hello World!&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;&lt;br /&gt;
        &amp;lt;?php echo &amp;quot;this is php!&amp;quot;; ?&amp;gt;                                                                                                                           &lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let's start the images; this time, php image should be pulled as well:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ docker-compose up -d&lt;br /&gt;
Pulling php (php:5.5-fpm)...&lt;br /&gt;
5.5-fpm: Pulling from library/php&lt;br /&gt;
efd26ecc9548: Already exists                  &amp;lt;-- the nginx image, already pulled&lt;br /&gt;
a3ed95caeb02: Download complete&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you get &amp;quot;''Service 'nginx' needs to be built, but --no-build was passed.''&amp;quot; message, run &amp;lt;tt&amp;gt;`docker-compose build`&amp;lt;/tt&amp;gt; and again &amp;lt;tt&amp;gt;`docker-compose up -d`&amp;lt;/tt&amp;gt;. Verify all is OK and started:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ docker ps&lt;br /&gt;
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                           NAMES&lt;br /&gt;
fd04b796e34f        dockertut_nginx     &amp;quot;nginx -g 'daemon off&amp;quot;   4 seconds ago       Up 4 seconds        443/tcp, 0.0.0.0:8080-&amp;gt;80/tcp   dockertut_nginx_1&lt;br /&gt;
402fb35b762e        php:5.5-fpm         &amp;quot;php-fpm&amp;quot;                5 seconds ago       Up 4 seconds        9000/tcp                        dockertut_php_1&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that nginx's image name has changed, since we have built a new one.&lt;br /&gt;
&lt;br /&gt;
Now, when you open ''localhost:8080'', you should get &amp;quot;this is php!&amp;quot; message. Open the ''index.php'' file, and edit it; the change should be immediately reflected. Sweet!&lt;br /&gt;
&lt;br /&gt;
=== Data Volumes ===&lt;br /&gt;
&lt;br /&gt;
Both the ''nginx'' and ''php'' vm's now use local folder through the ''volumes'' directive.&lt;br /&gt;
&lt;br /&gt;
Better yet is to have a separate container; we'll build this container based on some image we're already using (to avoid having yet another image downloaded), but it won't be running - it'll just sit there, collecting data. Change ''docker-compose.yml'' like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;nginx:&lt;br /&gt;
    build:&lt;br /&gt;
        ./docker/nginx/&lt;br /&gt;
    ports:&lt;br /&gt;
        - 8080:80&lt;br /&gt;
    links:&lt;br /&gt;
        - php&lt;br /&gt;
    volumes_from:&lt;br /&gt;
        - app&lt;br /&gt;
&lt;br /&gt;
php:&lt;br /&gt;
    image: php:5.5-fpm&lt;br /&gt;
    expose:&lt;br /&gt;
        - 9000&lt;br /&gt;
    volumes_from:&lt;br /&gt;
        - app&lt;br /&gt;
&lt;br /&gt;
app:&lt;br /&gt;
    # it's good practice to &amp;quot;reuse&amp;quot; some image, not to have yet another one pulled&lt;br /&gt;
    image: php:5.5-fpm&lt;br /&gt;
    volumes:&lt;br /&gt;
        - .:/var/www/html&lt;br /&gt;
    # container won't run - it'll execute `true` and sit there, collecting data&lt;br /&gt;
    command: &amp;quot;true&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let's check all is OK:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ docker-compose up -d&lt;br /&gt;
Creating dockertut_app_1...&lt;br /&gt;
Recreating dockertut_php_1...&lt;br /&gt;
Recreating dockertut_nginx_1...&lt;br /&gt;
&lt;br /&gt;
  # list all containers (note that 'app' container is not listed in `ps`, since it's not running):&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                           NAMES&lt;br /&gt;
af0110364abf        dockertut_nginx     &amp;quot;nginx -g 'daemon off&amp;quot;   2 minutes ago       Up 2 minutes               443/tcp, 0.0.0.0:8080-&amp;gt;80/tcp   dockertut_nginx_1&lt;br /&gt;
94a1c3d317dd        php:5.5-fpm         &amp;quot;php-fpm&amp;quot;                2 minutes ago       Up 2 minutes               9000/tcp                        dockertut_php_1&lt;br /&gt;
861cca283ceb        php:5.5-fpm         &amp;quot;true&amp;quot;                   2 minutes ago       Exited (0) 2 minutes ago                                   dockertut_app_1&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and check that ''localhost:8080'' is still responding.&lt;br /&gt;
&lt;br /&gt;
=== Adding MySQL ===&lt;br /&gt;
&lt;br /&gt;
Update the  'php' section:&lt;br /&gt;
&amp;lt;pre&amp;gt;php:&lt;br /&gt;
    build:&lt;br /&gt;
        ./docker/php/&lt;br /&gt;
    expose:&lt;br /&gt;
        - 9000&lt;br /&gt;
    links:&lt;br /&gt;
        - mysql&lt;br /&gt;
    volumes_from:&lt;br /&gt;
        - app&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;mysql:&lt;br /&gt;
    image: mysql:latest&lt;br /&gt;
    volumes_from:&lt;br /&gt;
        - mysqldata&lt;br /&gt;
    # set environment variables                                                                                                                                 &lt;br /&gt;
    environment:&lt;br /&gt;
        MYSQL_ROOT_PASSWORD: secret&lt;br /&gt;
        MYSQL_DATABASE: test&lt;br /&gt;
        MYSQL_USER: test&lt;br /&gt;
        MYSQL_PASSWORD: test&lt;br /&gt;
&lt;br /&gt;
mysqldata:&lt;br /&gt;
    image: mysql:latest&lt;br /&gt;
    volumes:&lt;br /&gt;
        # the /var/lib/mysql will be present in container, and &amp;quot;somewhere&amp;quot; on host&lt;br /&gt;
        - /var/lib/mysql&lt;br /&gt;
    command: &amp;quot;true&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, create ''./docker/php/Dockerfile'':&lt;br /&gt;
&amp;lt;pre&amp;gt;FROM php:5.5-fpm&lt;br /&gt;
RUN docker-php-ext-install pdo_mysql&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we're all set to &amp;lt;tt&amp;gt;`docker-compose build`&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;`docker-compose up -d`&amp;lt;/tt&amp;gt;. Let's check what containers we have now:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ docker ps -a&lt;br /&gt;
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                           NAMES&lt;br /&gt;
e43265be9680        dockertut_nginx     &amp;quot;nginx -g 'daemon off&amp;quot;   16 seconds ago      Up 14 seconds               443/tcp, 0.0.0.0:8080-&amp;gt;80/tcp   dockertut_nginx_1&lt;br /&gt;
48cd3b544fb1        dockertut_php       &amp;quot;php-fpm&amp;quot;                19 seconds ago      Up 17 seconds               9000/tcp                        dockertut_php_1&lt;br /&gt;
0e4f40d9ae8b        mysql:latest        &amp;quot;docker-entrypoint.sh&amp;quot;   21 seconds ago      Up 20 seconds               3306/tcp                        dockertut_mysql_1&lt;br /&gt;
963440e29d89        mysql:latest        &amp;quot;docker-entrypoint.sh&amp;quot;   22 seconds ago      Exited (0) 20 seconds ago                                   dockertut_mysqldata_1&lt;br /&gt;
1458644df104        php:5.5-fpm         &amp;quot;true&amp;quot;                   4 minutes ago       Exited (0) 4 minutes ago                                    dockertut_app_1&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that all is set up, we can check where did docker mount the folder on host, that is seen as ''/var/lib/mysql'' in ''mysqldata'' instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ docker inspect dockertut_mysqldata_1&lt;br /&gt;
...&lt;br /&gt;
        &amp;quot;Mounts&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;Name&amp;quot;: &amp;quot;d1352deaff99b25ee68bc53c07150b12b5eb7028b6182f1c97f71f7e21c8ee1d&amp;quot;,&lt;br /&gt;
                &amp;quot;Source&amp;quot;: &amp;quot;/var/lib/docker/volumes/d1352deaff99b25ee68bc53c07150b12b5eb7028b6182f1c97f71f7e21c8ee1d/_data&amp;quot;,&lt;br /&gt;
                &amp;quot;Destination&amp;quot;: &amp;quot;/var/lib/mysql&amp;quot;,&lt;br /&gt;
...&amp;lt;/pre&amp;gt;&lt;br /&gt;
The ''Source'' is the folder on host that docker mounted as ''Destination'' in VM.&lt;br /&gt;
&lt;br /&gt;
If you want all volumes removed when deleting docker container, use&lt;br /&gt;
 $ docker rm -v ''container-id''&lt;br /&gt;
Otherwise, the volumes will stay on your disk, taking up space.&lt;br /&gt;
&lt;br /&gt;
You can also list all volumes registered by docker:&lt;br /&gt;
 $ docker volume ls&lt;br /&gt;
and use this to remove all &amp;quot;dangling&amp;quot; volumes:&lt;br /&gt;
 $ docker volume rm $(docker volume ls -qf dangling=true)&lt;br /&gt;
&lt;br /&gt;
Let's check if mysql is up and running, through terminal. You can open interactive terminal in image like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ docker exec -it dockertut_mysql_1 /bin/bash&lt;br /&gt;
root@0e4f40d9ae8b:/# mysql -u root -p&lt;br /&gt;
Enter password: &lt;br /&gt;
Welcome to the MySQL monitor.  Commands end with ; or \g.&lt;br /&gt;
...&lt;br /&gt;
mysql&amp;gt; _&amp;lt;/pre&amp;gt;&lt;br /&gt;
Neat, huh? The ''-i'' means to run interactive command, ''-t'' to run in terminal.&lt;br /&gt;
&lt;br /&gt;
== Manage Docker as non-root User ==&lt;br /&gt;
&lt;br /&gt;
By creating &amp;lt;tt&amp;gt;docker&amp;lt;/tt&amp;gt; group, and adding users to it, you may select users that can manage docker daemon and processes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo groupadd docker&lt;br /&gt;
$ sudo usermod -aG docker $USER&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, restart your machine (or, log out and in, and stop and start the docker daemon), and you should be able to control docker without the need for &amp;lt;tt&amp;gt;sudo&amp;lt;/tt&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Linux_Administration</id>
		<title>Short Notes on Linux Administration</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Linux_Administration"/>
				<updated>2019-11-21T08:19:43Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Reset Compiz to Default Settings ==&lt;br /&gt;
&lt;br /&gt;
 gconftool-2 --recursive-unset /apps/compiz&lt;br /&gt;
and restart.&lt;br /&gt;
&lt;br /&gt;
== Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
If you're getting &amp;quot;'''stat=Deferred: Connection refused by [127.0.0.1]'''&amp;quot; log messages from ''sendmail'', try adding the following line to your '''/etc/mail/sendmail.mc''' file:&lt;br /&gt;
 DAEMON_OPTIONS(`Port=smtp, Addr=127.0.0.1, Name=MTA')&lt;br /&gt;
under the &amp;quot;General defines&amp;quot; section.&lt;br /&gt;
&lt;br /&gt;
Also, make sure the &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt; daemon is running:&lt;br /&gt;
 ps aux | grep sendmail&lt;br /&gt;
If not, run it using&lt;br /&gt;
 sendmail -bd -q1m&lt;br /&gt;
where ''-q'' parameter chooses how often the email queue's new messages should be processed (here, every minute).&lt;br /&gt;
&lt;br /&gt;
To test if this all works, use&lt;br /&gt;
 echo -e &amp;quot;Subject: Hello\nTesting the mailer...&amp;quot; | sendmail -f test@test.com ''myrealaddress@mail.com''&lt;br /&gt;
&lt;br /&gt;
The advantage of &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt; over &amp;lt;tt&amp;gt;mail&amp;lt;/tt&amp;gt; is that the ''from'' address need not be a valid email address... well... advantage?&lt;br /&gt;
&lt;br /&gt;
== Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
On most systems, &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt; comes as a package, and typically gets started during the boot from the &amp;lt;tt&amp;gt;init.d&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;rc.d&amp;lt;/tt&amp;gt; scripts.&lt;br /&gt;
&lt;br /&gt;
If you want/need to start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt; manually, or it has died, use&lt;br /&gt;
 sendmail -bd&lt;br /&gt;
or, for debugging purposes&lt;br /&gt;
 sendmail -bD&lt;br /&gt;
that will start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt; daemon, but will keep it in foreground, so you can see its output.&lt;br /&gt;
&lt;br /&gt;
== Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
The easiest way is to create the message file with all necessary definitions, e.g.&lt;br /&gt;
&amp;lt;pre&amp;gt;To: Mr. Recepient &amp;lt;recepient@hosting.com&amp;gt;&lt;br /&gt;
Subject: This is a fine example of a subject&lt;br /&gt;
Date: 2011-08-15 20:00:00 +0000&lt;br /&gt;
From: Mr. Sender &amp;lt;sender@hosting.com&amp;gt;&lt;br /&gt;
Content-Type: text/plain; charset=utf-8&lt;br /&gt;
Content-Transfer-Encoding: 8bit&lt;br /&gt;
Content-Disposition: inline&lt;br /&gt;
User-Agent: My email service&lt;br /&gt;
&lt;br /&gt;
The body of the message comes here, after a single blank line...&amp;lt;/pre&amp;gt;&lt;br /&gt;
and then feed this file to &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;sendmail -t &amp;lt; message_file.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Find and Mark Bad Blocks ==&lt;br /&gt;
&lt;br /&gt;
To test partition &amp;lt;tt&amp;gt;/dev/sdXN&amp;lt;/tt&amp;gt; (such as, &amp;lt;tt&amp;gt;/dev/sda1&amp;lt;/tt&amp;gt;) for bad blocks simply run:&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo backblocks -sv /dev/sdXN &amp;gt; ~/bad-blocks-list&lt;br /&gt;
$ fsck -l ~/bad-blocks-list /dev/sdXN&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using TLP to Optimize Battery Lifetime ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# check TLP status and system info&lt;br /&gt;
$ sudo tlp-stat -s&lt;br /&gt;
&lt;br /&gt;
--- TLP 1.1 --------------------------------------------&lt;br /&gt;
&lt;br /&gt;
+++ System Info&lt;br /&gt;
[...]&lt;br /&gt;
&lt;br /&gt;
+++ TLP Status&lt;br /&gt;
State          = enabled&lt;br /&gt;
Last run       = 09:13:49,    403 sec(s) ago&lt;br /&gt;
Mode           = battery&lt;br /&gt;
Power source   = battery&lt;br /&gt;
&lt;br /&gt;
# get battery information&lt;br /&gt;
$ sudo tlp-stat -b&lt;br /&gt;
&lt;br /&gt;
--- TLP 1.1 --------------------------------------------&lt;br /&gt;
&lt;br /&gt;
+++ Battery Status&lt;br /&gt;
/sys/class/power_supply/BAT0/manufacturer                   = CPT-COS&lt;br /&gt;
/sys/class/power_supply/BAT0/model_name                     = L17C4PB0&lt;br /&gt;
/sys/class/power_supply/BAT0/cycle_count                    = (not supported)&lt;br /&gt;
/sys/class/power_supply/BAT0/energy_full_design             =  45520 [mWh]&lt;br /&gt;
/sys/class/power_supply/BAT0/energy_full                    =  44540 [mWh]&lt;br /&gt;
/sys/class/power_supply/BAT0/energy_now                     =  37370 [mWh]&lt;br /&gt;
/sys/class/power_supply/BAT0/power_now                      =  20057 [mW]&lt;br /&gt;
/sys/class/power_supply/BAT0/status                         = Discharging&lt;br /&gt;
&lt;br /&gt;
Charge                                                      =   83.9 [%]&lt;br /&gt;
Capacity                                                    =   97.8 [%]&lt;br /&gt;
&lt;br /&gt;
# CPU temperature and fan speed&lt;br /&gt;
$ sudo tlp-stat -t&lt;br /&gt;
&lt;br /&gt;
# CPU info&lt;br /&gt;
$ sudo tlp-stat -p&lt;br /&gt;
&lt;br /&gt;
# warnings&lt;br /&gt;
$ sudo tlp-stat -w&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2019-11-21T08:12:58Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Linux Administration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
* Using TLP to optimize battery lifetime&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Main_Page</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Main_Page"/>
				<updated>2019-11-18T16:18:21Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* Python */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the '''PaskvilWiki'''!&lt;br /&gt;
&lt;br /&gt;
The future shape of this wiki is unknown for now, let's hope it'll be something good...&lt;br /&gt;
&lt;br /&gt;
This is partially a private wiki - viewing is allowed to all, but editing is allowed only to registered users. &lt;br /&gt;
&lt;br /&gt;
This is more of a prevention than denial - I don't have time to monitor and moderate edits; - you're more than welcome to request registration, all contributors are very much welcome!&lt;br /&gt;
&lt;br /&gt;
Just write me at josef.at.paskvil.dot.com.&lt;br /&gt;
&lt;br /&gt;
== References and Tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== [[emacs and slime reference|Emacs and Slime Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Reference]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small jQuery Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small SPARQL, RDQL, etc. Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
== Short Notes - Tips and Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[Small 4store How-To|4store]] ===&lt;br /&gt;
&lt;br /&gt;
* setup and installation&lt;br /&gt;
* running 4store&lt;br /&gt;
* data import&lt;br /&gt;
* data import and querying from Python&lt;br /&gt;
* Turtle file printer (in Python)&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Apache|Apache]] ===&lt;br /&gt;
&lt;br /&gt;
* Note on serving of local files&lt;br /&gt;
* Self-Signed SSL Certificate&lt;br /&gt;
* Enable SSL/HTTPS in Apache&lt;br /&gt;
* &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;mod_rewrite&amp;lt;/tt&amp;gt; Tricks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on AWS|AWS]] ===&lt;br /&gt;
&lt;br /&gt;
* Debugging (lack of) connection to instance&lt;br /&gt;
* Authorization header being removed by ElasticBeanstalk&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Bash|Bash]] ===&lt;br /&gt;
&lt;br /&gt;
* Extensions and File Name&lt;br /&gt;
* File Test Operators&lt;br /&gt;
* ''Commands and Shortcuts''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ sudo !!                         - run last command as root&lt;br /&gt;
$ !!:gs/foo/bar                   - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ ^foo^bar                        - run last command, replacing 'foo' with 'bar'&lt;br /&gt;
$ cp filename{,.bak}              - create a .bak copy of file&lt;br /&gt;
&amp;lt;Ctrl-x&amp;gt; &amp;lt;Ctrl-e&amp;gt;                 - open $EDITOR to edit current command line; upon exit, content will be run&lt;br /&gt;
$ &amp;lt;space&amp;gt;command                  - run the command without saving it in history&lt;br /&gt;
$ &amp;gt; file.txt                      - empty a file&lt;br /&gt;
&amp;lt;Alt+.&amp;gt;                           - put last argument on cursor place; repeat to cycle through&lt;br /&gt;
$ (cd /tmp &amp;amp;&amp;amp; ls)                 - jump to /tmp, execute ls, and jump back here&lt;br /&gt;
$ pushd /tmp .... $ popd          - goes to /tmp, remembering current location; at later time, popd will bring you back&lt;br /&gt;
$ \command                        - run command without using aliases&lt;br /&gt;
$ rm !(pattern|pattern)           - delete files that do not match given patterns&lt;br /&gt;
$ find . -mtime +5 -exec rm {} \; - delete all files in this folder that are older than 5 days&lt;br /&gt;
&amp;lt;Ctrl-u&amp;gt; ... &amp;lt;Ctrl-y&amp;gt;             - Ctrl+u will cut current command, then you can do whatever you need, and Ctrl+y will paste it back&lt;br /&gt;
$ date -d @1234567890             - convert unix timestamp to human-readable&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Informations''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ mount | column -t               - pretty-print mount table&lt;br /&gt;
$ cat /etc/issue                  - display distro name&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''Small Tricks''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ echo $(printf '%q' &amp;quot;A\&amp;quot;B&amp;quot;)      - prints escaped string (in this case, &amp;gt; A\&amp;quot;B &amp;lt;)&lt;br /&gt;
$ mount -t tmpfs tmpfs /mnt -o size=1024m      - mount temporary RAM partition (fast access, non-persistent!)&lt;br /&gt;
$ disown -a &amp;amp;&amp;amp; exit               - exit the shell while keeping all running processes alive&lt;br /&gt;
$ ssh -t remote_host screen -r    - directly connect to a remote screen process&lt;br /&gt;
$ for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip &amp;gt; &amp;quot;$I.sql.gz&amp;quot;; done&lt;br /&gt;
                                  - backup all databases into individual files&lt;br /&gt;
$ fuser -k filename               - kill process that is locking given file&lt;br /&gt;
$ readom dev=/dev/scd0 f=/path/to/image.iso    - create CD/DVD ISO image&lt;br /&gt;
$ diff -rq folder-1 folder-2      - compare 2 folders (files missing or differing)&lt;br /&gt;
$ mkdir -p a/deep/dir/tree        - create nested directories fast&lt;br /&gt;
$ mount file.iso /mnt/iso -o loop - mount ISO file as drive /mnt/iso (dir has to preexist)&lt;br /&gt;
$ sudo touch /forcefsck           - force a file system check on the next reboot&lt;br /&gt;
$ ls | while read f; do process_file &amp;quot;$f&amp;quot;; done    - iterate through files even if they contain space in name&lt;br /&gt;
$ while read f; do process_file &amp;quot;$f&amp;quot;; done &amp;lt; &amp;lt;(ls) - iterates through files, but does not create sub-process (outside scope is visible)&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''lsof''&lt;br /&gt;
&amp;lt;pre&amp;gt;$ lsof -nPi                       - list network connections&lt;br /&gt;
$ netstat -tlnp                   - print all listening ports with PID's (run as root to see all process names)&lt;br /&gt;
$ lsof -c gnome-terminal          - list files opened by given command&lt;br /&gt;
$ lsof +D [folder]                - discover all open files in the [folder]&lt;br /&gt;
$ lsof -p [pid]                   - list files opened by given PID&lt;br /&gt;
$ lsof -i :8080                   - list programs that have port 8080 open (&amp;quot;who to kill&amp;quot; if you get &amp;quot;port already in use&amp;quot;)&lt;br /&gt;
$ if [ `lsof -- file | wc -l` -ne 0 ] ... - tests if file is open by some process&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on C/C++|C/C++]] ===&lt;br /&gt;
&lt;br /&gt;
* How to clean up after child thread&lt;br /&gt;
* Non-blocking IO using sockets&lt;br /&gt;
* Shared Libraries on Linux+GCC&lt;br /&gt;
* Singleton&lt;br /&gt;
* &amp;lt;tt&amp;gt;std::move&amp;lt;/tt&amp;gt; Semantics&lt;br /&gt;
* Converting between &amp;lt;tt&amp;gt;std::string&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;std::wstring&amp;lt;/tt&amp;gt; in C++11&lt;br /&gt;
&lt;br /&gt;
=== cURL (in terminal) ===&lt;br /&gt;
&lt;br /&gt;
Use '''-s''' option to make &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; silent.&lt;br /&gt;
&lt;br /&gt;
* POST to server using cURL:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --data &amp;quot;key1=value1&amp;amp;key2=value2&amp;quot; http://www.example.com/post.php&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Upload to FTP server (with credentials), having connection timeout 60 seconds, and 120 seconds maximum operation time:&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --connect-timeout 60 -m 120 -T file.ext &amp;quot;ftp://12.34.56.78/folder&amp;quot; --user user:pass&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Download from FTP server (with credentials):&lt;br /&gt;
&amp;lt;pre&amp;gt;curl --user user:pass &amp;quot;ftp://12.34.56.78/folder/file.ext&amp;quot; -o ~/Downloads/file.ext&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Small Docker Notes|Docker]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small elasticsearch Notes|ElasticSearch]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation&lt;br /&gt;
* What You Get&lt;br /&gt;
* Indexing, Routing, etc.&lt;br /&gt;
* Deleting&lt;br /&gt;
* Getting and Multi-Getting&lt;br /&gt;
* Updating&lt;br /&gt;
* Search and Query DSL&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ffmpeg|ffmpeg]] ===&lt;br /&gt;
&lt;br /&gt;
* ''process all files, may include spaces in file name:''&lt;br /&gt;
 ls *.avi | while read f; do ffmpeg -i &amp;quot;$f&amp;quot; ''...params...'' &amp;quot;$f.mkv&amp;quot;; done&lt;br /&gt;
* ''if you're having problems with input format, passing video through mpeg typically helps:''&lt;br /&gt;
 ffmpeg -i file.mkv -qscale 2 -f mpeg - | ffmpeg -i - ''...params...'' file.avi&lt;br /&gt;
* ''downmix 5.1 dolby to normal stereo:''&lt;br /&gt;
 ffmpeg -i file.mkv ''...params...'' -acodec libmp3lame -ar 44100 -ac 2 file.avi&lt;br /&gt;
* ''add an overlay image to the video:''&lt;br /&gt;
 ffmpeg -i input.mp4 -i image.png -filter_complex &amp;quot;[0:v][1:v] overlay=''x'':''y'':enable='between(t,0,20)'&amp;quot; -pix_fmt yuv420p -c:a copy output.mp4&lt;br /&gt;
This will add ''image.png'' as an overlay at position ''x'', ''y'' over the ''imput.mp4'' video, for the first 20 seconds.&lt;br /&gt;
* ''fade in and out, first and last 25 frames of a 1000 frame video''&lt;br /&gt;
 ffmpeg -i input.mp4 -vf &amp;quot;fade=in:0:25,fade=out:975:25&amp;quot; -acodec copy out.mp4&lt;br /&gt;
&lt;br /&gt;
==== [[Short Notes on ffmpeg|more on ffmpeg]] ====&lt;br /&gt;
&lt;br /&gt;
* Rip DVD into FLV (or anything else)&lt;br /&gt;
* Video File with Still Image and Audio&lt;br /&gt;
* Concatenate Videos&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Flask and Flask-RestPlus|Flask and Flask-RestPlus]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on git|git]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Small Kyoto Cabinet and Kyoto Tycoon Notes|Kyoto Cabinet and Kyoto Tycoon]] ===&lt;br /&gt;
&lt;br /&gt;
* Setup and Install Kyoto Cabinet&lt;br /&gt;
* Setup and Install Kyoto Tycoon&lt;br /&gt;
* KT's RPC API Reference&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Linux Administration|Linux Administration]] ===&lt;br /&gt;
&lt;br /&gt;
* Reset Compiz to Default Settings&lt;br /&gt;
* Enable and Start &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Installing &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Sending Emails using &amp;lt;tt&amp;gt;sendmail&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Find and Mark Bad Blocks&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MAC OSX|MAC OSX]] ===&lt;br /&gt;
&lt;br /&gt;
* Asynchronous Execution&lt;br /&gt;
** ''NSThread''&lt;br /&gt;
** ''performSelectorInBackground''&lt;br /&gt;
** ''dispatch_async''&lt;br /&gt;
* ''MacPorts''&lt;br /&gt;
 $ sudo port selfupdate&lt;br /&gt;
 $ sudo port upgrade outdated&lt;br /&gt;
 $ sudo port uninstall inactive&lt;br /&gt;
 $ (just once) sudo port install port_cutleaves&lt;br /&gt;
 $ sudo port_cutleaves&lt;br /&gt;
&lt;br /&gt;
=== [[Small MongoDB Notes|MongoDB]] ===&lt;br /&gt;
&lt;br /&gt;
* Installation on Ubuntu&lt;br /&gt;
* Troubleshooting on Desktop&lt;br /&gt;
* Use in PHP via PECL driver&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on MySQL|MySQL]] ===&lt;br /&gt;
&lt;br /&gt;
* Error 1045: Access denied&lt;br /&gt;
* The &amp;lt;tt&amp;gt;insert ... on duplicate key update&amp;lt;/tt&amp;gt; Pitfall&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PDF|PDF]] ===&lt;br /&gt;
&lt;br /&gt;
* Merging PDF Files using GhostScript&lt;br /&gt;
* Cutting PDF Files using GhostScript&lt;br /&gt;
* Converting to PDF using GhostScript&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on PHP|PHP]] ===&lt;br /&gt;
&lt;br /&gt;
* Convert Accented Characters to Non-Accented&lt;br /&gt;
* Upload a File using cURL&lt;br /&gt;
* HTTP Post in Pure PHP (without cURL)&lt;br /&gt;
* Prevent Client Disconnect from Killing PHP&lt;br /&gt;
* Disconnect Client and Continue Processing&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Python|Python]] ===&lt;br /&gt;
&lt;br /&gt;
* Timing, and memory, on Linux&lt;br /&gt;
* Importing Files&lt;br /&gt;
* uWSGI, nginx, Flask&lt;br /&gt;
* Decorators&lt;br /&gt;
* virtualenv&lt;br /&gt;
* SQLAlchemy&lt;br /&gt;
&lt;br /&gt;
=== [[RedBeanPHP Cheat Sheet]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on RESTful APIs|RESTful APIs]] ===&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Security|Security]] ===&lt;br /&gt;
&lt;br /&gt;
* Password Generators&lt;br /&gt;
* SSH Access using pubkey's Authentication&lt;br /&gt;
* Using RSync together with SSH&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on SVN|Subversion/SVN]] ===&lt;br /&gt;
&lt;br /&gt;
* Simple Guide to SVN Client&lt;br /&gt;
* Creating a SVN Repository&lt;br /&gt;
* Moving a SVN Repository&lt;br /&gt;
* Change Repository URL (Subversion 1.7+)&lt;br /&gt;
* Setup a SVN Server on a Shared Hosting with no ''root'' Access&lt;br /&gt;
* creating and applying patch (the &amp;lt;tt&amp;gt;--diff-cmd&amp;lt;/tt&amp;gt; is necessary in case you set some graphical diff-viewer in &amp;lt;tt&amp;gt;~/.subversion/config&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;cd root_of_project&lt;br /&gt;
svn di --diff-cmd diff &amp;gt; ~/patch.diff&lt;br /&gt;
cd root_of_other_project&lt;br /&gt;
patch -p0 -i ~/patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
* ''svn:externals'' - pull ''repo1'' into ''dir1'', and ''repo2'' into ''dir2'':&lt;br /&gt;
&amp;lt;pre&amp;gt;echo -e 'dir1 svn://repo1\ndir2 svn://repo2' &amp;gt; repos.txt&lt;br /&gt;
svn propset svn:externals . -F repos.txt&amp;lt;/pre&amp;gt;&lt;br /&gt;
validate with &amp;quot; ''svn propget svn:externals .'' &amp;quot; .&lt;br /&gt;
&lt;br /&gt;
=== Ubuntu / Debian / Gnome etc. ===&lt;br /&gt;
&lt;br /&gt;
* restrict gnome app switcher to current workspace only:&lt;br /&gt;
&amp;lt;pre&amp;gt;gsettings set org.gnome.shell.app-switcher current-workspace-only true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* restore or undelete (config) file or directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;# 1. check what package file or folder belongs to&lt;br /&gt;
$ dpkg -S /path/my.conf&lt;br /&gt;
# 2.a replace the config file; if it exists, will offer diff&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall &amp;lt;package-name&amp;gt;&lt;br /&gt;
# 2.b restore the directory&lt;br /&gt;
$ sudo apt-get -o Dpkg::Options::=&amp;quot;--force-confask&amp;quot; install --reinstall $(dpkg -S /etc/some/directory | sed 's/,//g; s/:.*//')&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on ViM|ViM]] ===&lt;br /&gt;
&lt;br /&gt;
* Delete all lines matching a pattern&lt;br /&gt;
* Directly type HTML entities&lt;br /&gt;
* Reformat a plain text paragraph&lt;br /&gt;
&amp;lt;pre&amp;gt;$ vim -x filename                      - open filename for editing, and save it encrypted (will prompt for a key)&lt;br /&gt;
:X                                     - set encryption for current file; use ':set key=' to disable encryption&lt;br /&gt;
                                       - put &amp;quot;set cm=blowfish&amp;quot; in your .vimrc to enable safer encryption by default&lt;br /&gt;
$ vim +10 [file] ; vim +/hello [file]  - open [file] at line 10, or at first occurrence of pattern 'hello' in file&lt;br /&gt;
:w !sudo tee %                         - save file via `sudo` (as root)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Wavelets|Wavelets]] ===&lt;br /&gt;
&lt;br /&gt;
* Integer Haar Wavelets in Python&lt;br /&gt;
&lt;br /&gt;
=== [[Short Notes on Web|Web - HTML, CSS, JS, jQuery, etc.]] ===&lt;br /&gt;
&lt;br /&gt;
* Multiple Submit Buttons and/or Multiple Forms on Page&lt;br /&gt;
* Make 'float' Elements Appear One under Another&lt;br /&gt;
* Upload a File via Form&lt;br /&gt;
* Override the IE's Problem with &amp;lt;tt&amp;gt;width&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Make an Element Fill In All the Remaining Space&lt;br /&gt;
&lt;br /&gt;
=== Other Short Notes ===&lt;br /&gt;
&lt;br /&gt;
==== [[Rip Video DVD that is not Finalized]] ====&lt;br /&gt;
&lt;br /&gt;
==== [[Install Apache and PHP to do Secure h264 Pseudo Streaming]] ====&lt;br /&gt;
&lt;br /&gt;
==== HTTP Response Codes ====&lt;br /&gt;
&lt;br /&gt;
This is not a definitive list, it's just stuff I use the most, and always forget which is which.&lt;br /&gt;
&lt;br /&gt;
* '''100''' - ''Continue''&lt;br /&gt;
* '''200''' - ''OK''&lt;br /&gt;
* '''201''' - ''Created''&lt;br /&gt;
* '''202''' - ''Accepted''&lt;br /&gt;
* '''204''' - ''No Content''&lt;br /&gt;
* '''301''' - ''Moved Permanently''&lt;br /&gt;
* '''302''' - ''Found'' (I typically use this instead of the '''307''' &amp;quot;''Temporary Redirect''&amp;quot;)&lt;br /&gt;
* '''304''' - ''Not Modified''&lt;br /&gt;
* '''400''' - ''Bad Request''&lt;br /&gt;
* '''401''' - ''Unauthorized''&lt;br /&gt;
* '''403''' - ''Forbidden''&lt;br /&gt;
* '''404''' - ''Not Found''&lt;br /&gt;
* '''405''' - ''Method Not Allowed'' (using GET on POST calls, etc. - must include &amp;quot;Allow&amp;quot; response header)&lt;br /&gt;
* '''406''' - ''Not Acceptable'' (mismatch of response format and &amp;quot;Accept&amp;quot; headers)&lt;br /&gt;
* '''500''' - ''Internal Server Error''&lt;br /&gt;
* '''501''' - ''Not Implemented''&lt;br /&gt;
* '''503''' - ''Service Unavailable''&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>https://wiki.paskvil.com/index.php/Short_Notes_on_Python</id>
		<title>Short Notes on Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.paskvil.com/index.php/Short_Notes_on_Python"/>
				<updated>2019-11-18T16:18:04Z</updated>
		
		<summary type="html">&lt;p&gt;Admin: /* virtualenv */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Timing, and memory, on Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
&lt;br /&gt;
On Linux, it's safer to use &amp;lt;tt&amp;gt;time.time()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;import time&lt;br /&gt;
t = time.time()&lt;br /&gt;
# do some stuff&lt;br /&gt;
print &amp;quot;stuff took %1.3f&amp;quot;, time.time() - t, &amp;quot;seconds&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
On Windows, AFAIK, it's safer to use &amp;lt;tt&amp;gt;time.clock()&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory ===&lt;br /&gt;
&lt;br /&gt;
For me, the following does a good job getting memory usage (in kB) on Linux:&lt;br /&gt;
&amp;lt;pre&amp;gt;import resource&lt;br /&gt;
print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss&amp;lt;/pre&amp;gt;&lt;br /&gt;
Since &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; is standard package, it should work on Windows too, but I don't know if it does, or what units are used if it works.&lt;br /&gt;
&lt;br /&gt;
== Importing Files ==&lt;br /&gt;
&lt;br /&gt;
If you need to import a file '../mylib/commons.py', you can use the following snippet:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;import sys, os&lt;br /&gt;
fld = os.path.realpath(os.path.abspath(os.path.join('..', 'mylib')))&lt;br /&gt;
if fld not in sys.path:&lt;br /&gt;
    sys.path.insert(0, fld)&lt;br /&gt;
import commons&lt;br /&gt;
&lt;br /&gt;
# use your commons.py module now...&lt;br /&gt;
commons.super_function()&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== uWSGI, nginx, Flask ==&lt;br /&gt;
&lt;br /&gt;
* install uwsgi (incl. uwsgi python plugin), python flask, and nginx,&lt;br /&gt;
&lt;br /&gt;
=== Setting Up uWSGI ===&lt;br /&gt;
&lt;br /&gt;
* create ''main.py'' file that will hold the server logic, for instance:&lt;br /&gt;
&amp;lt;pre&amp;gt;from flask import Flask&lt;br /&gt;
&lt;br /&gt;
app = Flask(__name__)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@app.route(&amp;quot;/&amp;quot;)&lt;br /&gt;
def hello():&lt;br /&gt;
    return &amp;quot;hello there!&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
* create uwsgi config file, ''wsgi.ini'' ('''minimal''' version here; read uwsgi docs for head-spinning array of configurables):&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
protocol        = http&lt;br /&gt;
plugin          = python&amp;lt;/pre&amp;gt;&lt;br /&gt;
* run uwsgi&lt;br /&gt;
 uwsgi --ini wsgi.ini&lt;br /&gt;
* check that all works on http://localhost:8000/&lt;br /&gt;
&lt;br /&gt;
=== Adding nginx Layer ===&lt;br /&gt;
&lt;br /&gt;
* remove the &amp;quot;protocol&amp;quot; directive from ''wsgi.ini'', and add &amp;quot;die-on-term&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;[uwsgi]&lt;br /&gt;
module          = main:app&lt;br /&gt;
master          = true&lt;br /&gt;
processes       = 5&lt;br /&gt;
socket          = 127.0.0.1:8000&lt;br /&gt;
plugin          = python&lt;br /&gt;
die-on-term     = true&amp;lt;/pre&amp;gt;&lt;br /&gt;
* add a new vhost to nginx - ''/etc/nginx/sites-available/app.nginx'':&lt;br /&gt;
&amp;lt;pre&amp;gt;server {&lt;br /&gt;
    listen 80;&lt;br /&gt;
    server_name my.awesome.domain;&lt;br /&gt;
    location / {&lt;br /&gt;
        include uwsgi_params;&lt;br /&gt;
        uwsgi_pass 127.0.0.1:8000;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
** communication through socket is also possible (see ''socket'', ''chmod-socket'', ''vacuum'' and other directives for uWSGI)&lt;br /&gt;
** of course, create link in ''/etc/nginx/sites-enabled/'', and restart nginx,&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - supervisor ===&lt;br /&gt;
&lt;br /&gt;
* install &amp;lt;tt&amp;gt;supervisor&amp;lt;/tt&amp;gt;&lt;br /&gt;
 apt-get install supervisor&lt;br /&gt;
* add/edit &amp;lt;tt&amp;gt;/etc/supervisord.conf&amp;lt;/tt&amp;gt; with content like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;[unix_http_server]&lt;br /&gt;
file=/run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[supervisord]&lt;br /&gt;
logfile=/var/log/supervisord.log&lt;br /&gt;
logfile_maxbytes=1MB&lt;br /&gt;
logfile_backups=1&lt;br /&gt;
loglevel=info ; (others: warn,debug,trace)&lt;br /&gt;
pidfile=/run/supervisord.pid&lt;br /&gt;
nodaemon=false&lt;br /&gt;
minfds=1024&lt;br /&gt;
minprocs=200&lt;br /&gt;
&lt;br /&gt;
[supervisorctl]&lt;br /&gt;
serverurl=unix:///run/supervisor.sock&lt;br /&gt;
&lt;br /&gt;
[program:your app]&lt;br /&gt;
directory=/path/to/app&lt;br /&gt;
command=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
autostart=true&lt;br /&gt;
autorestart=true&lt;br /&gt;
stdout_logfile=/var/log/uwsgi.log&lt;br /&gt;
redirect_stderr=true&lt;br /&gt;
stopsignal=QUIT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Run uWSGI daemon on boot - systemd ===&lt;br /&gt;
&lt;br /&gt;
* create ''systemd'' file for uWSGI, ''/etc/systemd/system/uwsgi-app.service'':&lt;br /&gt;
&amp;lt;pre&amp;gt;[Unit]&lt;br /&gt;
Description=Job that runs the uWSGI app&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
WorkingDirectory=/home/project/flask-test/&lt;br /&gt;
ExecStart=/usr/bin/uwsgi --ini wsgi.ini&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you can start and stop the uwsgi service using:&lt;br /&gt;
 # systemctl start uwsgi-app.service&lt;br /&gt;
 # systemctl stop uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
Once you're happy with the settings, ''enable'' the daemon to be run on boot:&lt;br /&gt;
 # systemctl enable uwsgi-app.service&lt;br /&gt;
&lt;br /&gt;
== Decorators ==&lt;br /&gt;
&lt;br /&gt;
''needs a bit of refreshment and updating...''&lt;br /&gt;
&lt;br /&gt;
[http://www.artima.com/weblogs/viewpost.jsp?thread=240845 based on].&lt;br /&gt;
&lt;br /&gt;
Decorators are simple and expressive way to modify function without editing the source of the function itself. Or, the other way around, to modify multiple functions in the same way, without code duplication (DRY).&lt;br /&gt;
&lt;br /&gt;
Decorators can be spotted in the code by starting with &amp;lt;tt&amp;gt;@&amp;lt;/tt&amp;gt; character. Decorator is a function (or class) that can do some additional work before or after the call to the decorated function. It can even call the decorated function multiple times, or not at all.&lt;br /&gt;
&lt;br /&gt;
Decorators can be implemented as closures (my fave), or as classes; the following approaches are equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a function (closure) as a decorator&lt;br /&gt;
def beforeAndAfter(f):&lt;br /&gt;
    def decorated_fn():&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
        f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
    return decorated_fn&lt;br /&gt;
&lt;br /&gt;
@entryExit&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# using a class as a decorator&lt;br /&gt;
class beforeAndAfter(object):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self, f):&lt;br /&gt;
        self.f = f&lt;br /&gt;
&lt;br /&gt;
    def __call__(self):&lt;br /&gt;
        print(&amp;quot;Before&amp;quot;, self.f.__name__)&lt;br /&gt;
        self.f()&lt;br /&gt;
        print(&amp;quot;After&amp;quot;, self.f.__name__)&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter&lt;br /&gt;
def func():&lt;br /&gt;
    print &amp;quot;func() is in da' house!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
func()&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in functional decorator, anything outside the body of &amp;lt;tt&amp;gt;decorated_fn()&amp;lt;/tt&amp;gt; is equivalent to content of the &amp;lt;tt&amp;gt;__init__()&amp;lt;/tt&amp;gt; constructor of the class-based decorator. This code is run during the initialization, only once for each decorated function, regardless of whether the decorated function is ever called in the code - you should avoid any heavy lifting there.&lt;br /&gt;
&lt;br /&gt;
Decorators can also accept arguments, and (obviously should) forward arguments to the decorated function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;def beforeAndAfter(p1, p2):&lt;br /&gt;
    def wrap(f):&lt;br /&gt;
        def wrapped_f(*args, **kwargs):&lt;br /&gt;
            print &amp;quot;Decorator arguments:&amp;quot;, p1, p2&lt;br /&gt;
            print(&amp;quot;Before&amp;quot;, f.__name__)&lt;br /&gt;
            f(*args, **kwargs)&lt;br /&gt;
            print(&amp;quot;After&amp;quot;, f.__name__)&lt;br /&gt;
        return wrapped_f&lt;br /&gt;
    return wrap&lt;br /&gt;
&lt;br /&gt;
@beforeAndAfter(&amp;quot;hello&amp;quot;, &amp;quot;world&amp;quot;)&lt;br /&gt;
def func(a, b=2):&lt;br /&gt;
    print &amp;quot;func() is in da' house,&amp;quot;, a, b&lt;br /&gt;
&lt;br /&gt;
func(1)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== virtualenv ==&lt;br /&gt;
&lt;br /&gt;
I prefer installing &amp;lt;tt&amp;gt;virtualenv&amp;lt;/tt&amp;gt; tool through &amp;lt;tt&amp;gt;pip&amp;lt;/tt&amp;gt;, to make sure those are in sync version-wise.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;# create a new venv&lt;br /&gt;
# it is better to keep venv's in some separate folder, not to pollute your project folder&lt;br /&gt;
$ virtualenv ~/.virtualenvs/my-new-env&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;log into&amp;quot; your venv; success can be seen by your command line being prefixed by venv name&lt;br /&gt;
$ source ~/.virtualenvs/my-new-env/bin/activate&lt;br /&gt;
&lt;br /&gt;
# now you can install anything you need, tucked away in your venv:&lt;br /&gt;
(my-new-env) $ pip install -r requirements.txt&lt;br /&gt;
&lt;br /&gt;
# when done, just deactivate&lt;br /&gt;
(my-new-env) $ deactivate&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SQLAlchemy ==&lt;br /&gt;
&lt;br /&gt;
=== Make SQLAlchemy Read-Only ===&lt;br /&gt;
&lt;br /&gt;
All write operations in SQLAlchemy pass through &amp;lt;tt&amp;gt;flush()&amp;lt;/tt&amp;gt; method of your session.&lt;br /&gt;
Just monkey-path it to do nothing!&lt;br /&gt;
&amp;lt;pre&amp;gt;engine = create_engine(&amp;quot;connection string&amp;quot;)&lt;br /&gt;
Session = sessionmaker(bind=engine, autoflush=False, autocommit=False)&lt;br /&gt;
session = Session()&lt;br /&gt;
session.flush = lambda *args,**kwargs: None&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	</feed>