search

Monday, March 27, 2017

linux: Print exit code of the last command

To print exit code of the last command type:
echo $?

debian: How to check if package is installed

To check if ca-certificates package is installed run this command:
dpkg -s ca-certificates

Saturday, March 11, 2017

fedora: Set up DLNA server

I you have smart TV or WIFI speaker like Sonos it is possible to play media content on them from your computer.

I tried 2 different DLNA servers: minidlnad and rygel.

My expierence with minidlnad was not that great. Configuration was easy but both speaker and TV were not able to see DLNA server running on my laptop quite often

So I tried rygel. Rygel is maintained by GNOME community. The application is great and very easy to use. The installation is simple:

sudo dnf install rygel

After appliction is installed you can start it from the terminal via command:

rygel

It will automatically inspect your Music, Video and Pictures folders and add their content to the database. Created DLNA server is immediately available on the client devices.

As an interesting bonus, rygel allows you to stream the output from your audio card. The idea is absolutely fantastic! However, I had a latency about 5 seconds which makes watching videos on your computer and playing the sound on the remote speaker very uncomfortable. If anyone knows how to fix it, please post the solution in the comments.

There is a very nice wiki article that describes how to achieve it.

There are 2 methods: with External plugin (which does all the job automatically) and with GstLaunch plugin

The first method did not work for me, so I would describe the second one

By default rygel uses configuration file located in /etc/rygel.conf. The file can also be used as a documentation. All available options are described very well. It is possible to overwrite default options by creating ~/.config/rygel.conf file.

Create file ~/.config/rygel.conf with the following content:

[general]
upnp-enabled=true

[Tracker]
enabled=false

[MediaExport]
enabled=true
uris=@MUSIC@;@VIDEOS@;

[GstLaunch]
enabled=true
launch-items=mypulseaudioflac
mypulseaudioflac-title=Audio Output on  @HOSTNAME@
mypulseaudioflac-mime=audio/flac
mypulseaudioflac-launch=pulsesrc device=upnp.monitor ! flacenc

Install dependencies:

sudo dnf install pavucontrol paprefs gupnp-tools

Configure pulseaudio to create a separate audio device for streaming with paprefs command

And that is it! When playing media files, select a proper audio output device:

You might need to restart OS to apply all changes.

Thursday, March 9, 2017

List data samples for faker

faker is a very useful library for generating beautiful test data. However, I was not able to find a proper description with all providers. All samples (plus some useless data) can be printed and inspected with the following code:
from faker import Factory as FakerFactory

faker = FakerFactory.create()
methods = [method for method in dir(faker) if callable(getattr(faker, method)) and not method.startswith("_")]
for item in methods:
    try:
        print u"- %s:" % item
        print u"  %s" % getattr(faker, item)()
    except TypeError:
        pass
The output is:
- address:
  25611 Senger Cove
Cadenmouth, HI 46932-8013
- am_pm:
  AM
- boolean:
  False
- bothify:
  07 sb
- bs:
  re-contextualize customized mindshare
- building_number:
  86338
- catch_phrase:
  Expanded uniform complexity
- century:
  III
- chrome:
  Mozilla/5.0 (Windows NT 6.0) AppleWebKit/5361 (KHTML, like Gecko) Chrome/14.0.879.0 Safari/5361
- city:
  Sporershire
- city_prefix:
  Lake
- city_suffix:
  port
- color_name:
  Indigo
- company:
  Flatley Inc
- company_email:
  kbaumbach@mckenzie.com
- company_suffix:
  LLC
- country:
  Syrian Arab Republic
- country_code:
  FI
- credit_card_expire:
  12/26
- credit_card_full:
  
Diners Club / Carte Blanche
Pierre Donnelly
36417005868777  04/26
CVC: 568
- credit_card_number:
  6011478274887340
- credit_card_provider:
  VISA 16 digit
- credit_card_security_code:
  081
- currency_code:
  RSD
- date:
  1982-04-04
- date_time:
  1999-05-19 00:50:24
- date_time_ad:
  1864-03-03 15:27:13
- date_time_between:
  2002-08-21 16:01:56
- date_time_between_dates:
  2017-03-08 21:56:07
- date_time_this_century:
  2016-01-14 03:30:51
- date_time_this_decade:
  2014-08-17 00:29:28
- date_time_this_month:
  2017-03-03 08:27:52
- date_time_this_year:
  2017-01-10 12:08:41
- day_of_month:
  04
- day_of_week:
  Saturday
- domain_name:
  altenwerth.com
- domain_word:
  cronawalker
- ean:
  3265654672776
- ean13:
  4119002606106
- ean8:
  13383411
- email:
  columbus64@gmail.com
- file_extension:
  png
- file_name:
  aperiam.html
- firefox:
  Mozilla/5.0 (Windows NT 6.1; it-IT; rv:1.9.2.20) Gecko/2012-07-23 16:34:01 Firefox/4.0
- first_name:
  Tella
- first_name_female:
  Oliva
- first_name_male:
  Arba
- format:
- free_email:
  milford.rempel@yahoo.com
- free_email_domain:
  yahoo.com
- geo_coordinate:
  -82.910152
- get_formatter:
- get_providers:
  [<faker.providers.user_agent.Provider object at 0x7fcce4201410>, <faker.providers.ssn.en_US.Provider object at 0x7fcce4201450>, <faker.providers.python.Provider object at 0x7fcce42013d0>, <faker.providers.profile.Provider object at 0x7fcce4201390>, <faker.providers.phone_number.en_US.Provider object at 0x7fcce4201350>, <faker.providers.person.en_US.Provider object at 0x7fcce4201310>, <faker.providers.misc.Provider object at 0x7fcce4201250>, <faker.providers.lorem.la.Provider object at 0x7fcce42012d0>, <faker.providers.job.en_US.Provider object at 0x7fcce4201290>, <faker.providers.internet.en_US.Provider object at 0x7fcce4201210>, <faker.providers.file.Provider object at 0x7fcce42011d0>, <faker.providers.date_time.Provider object at 0x7fcce4201190>, <faker.providers.currency.Provider object at 0x7fcce4201150>, <faker.providers.credit_card.Provider object at 0x7fcce4201110>, <faker.providers.company.en_US.Provider object at 0x7fcce4201090>, <faker.providers.color.en_US.Provider object at 0x7fcce42010d0>, <faker.providers.barcode.Provider object at 0x7fcce4201050>, <faker.providers.address.en_US.Provider object at 0x7fcce41e9fd0>]
- hex_color:
  #69d7c0
- image_url:
  http://www.lorempixum.com/373/972
- internet_explorer:
  Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.01; Trident/3.1)
- ipv4:
  129.146.124.124
- ipv6:
  ef5e:860d:c643:8233:0ff0:d40d:7739:9844
- iso8601:
  2007-01-25T19:03:46
- job:
  Dancer
- language_code:
  de
- last_name:
  Romaguera
- last_name_female:
  Heidenreich
- last_name_male:
  Bogan
- latitude:
  62.9329675
- lexify:
  UGTW
- linux_platform_token:
  X11; Linux x86_64
- linux_processor:
  x86_64
- locale:
  ru_TO
- longitude:
  -49.789527
- mac_address:
  41:9e:ad:ca:2a:fe
- mac_platform_token:
  Macintosh; PPC Mac OS X 10_5_2
- mac_processor:
  Intel
- md5:
  04c1004fa2b0de119d764c4ec41e567d
- military_apo:
  PSC 0750, Box 3490
- military_dpo:
  Unit 1372 Box 0808
- military_ship:
  USNV
- military_state:
  AE
- mime_type:
  message/rfc822
- month:
  11
- month_name:
  February
- name:
  Dorcas Wolff MD
- name_female:
  Amy Tromp
- name_male:
  Colvin Hoppe
- null_boolean:
  False
- numerify:
  597
- opera:
  Opera/9.27.(Windows NT 6.2; it-IT) Presto/2.9.173 Version/11.00
- paragraph:
  Ex est maiores et maiores id voluptatem velit iure. Ratione ad enim sed. Quidem ea vel esse quis molestiae quisquam tempora.
- paragraphs:
  [u'Ipsum consequatur et et et et. Voluptatem qui totam veritatis. Quasi vitae autem quos magnam ducimus. Doloremque minima perferendis quibusdam mollitia doloremque. Et temporibus porro quia eveniet sunt.', u'Neque nihil cupiditate sunt. Velit ducimus sint qui eaque nam.', u'Sequi labore laudantium expedita iusto aspernatur quibusdam ipsa hic. Et delectus numquam et fugit. Et quo explicabo quia voluptatem molestias blanditiis omnis. Mollitia facilis molestiae sunt aut eius quia.']
- parse:
- password:
  H$E4isuB__
- phone_number:
  322-309-6514
- postalcode:
  36510
- postalcode_plus4:
  31785-2317
- postcode:
  63240
- prefix:
  Dr.
- prefix_female:
  Miss
- prefix_male:
  Mr.
- profile:
  {'website': [u'http://feest.com/', u'http://runolfsson.info/', u'http://www.wiegand.com/', u'http://www.rennerzemlak.org/'], 'username': u'bogisich.forest', 'name': u'Lorenz Friesen III', 'blood_group': 'A+', 'residence': u'87593 Douglas Pike\nBeahanberg, NY 08971-4439', 'company': u'Ratke and Sons', 'address': u'3721 Rath Springs\nMillerbury, AK 65443-3366', 'birthdate': '1985-10-14', 'sex': 'M', 'job': 'Scientist, research (medical)', 'ssn': u'658-53-8410', 'current_location': (Decimal('-69.179215'), Decimal('73.080343')), 'mail': u'natalee03@yahoo.com'}
- provider:
- pybool:
  False
- pydecimal:
  93907633.3459
- pydict:
  {u'non': u'Sint at et ut ut.', u'voluptas': datetime(2011, 6, 30, 13, 28, 24), u'in': u'Consequatur modi ut.', u'temporibus': u'nberge@gmail.com', u'quam': 5946, u'quia': -50185653292693.0, u'corporis': 44989.34539971, u'aspernatur': datetime(2001, 5, 8, 5, 0, 4), u'id': u'Voluptas et.', u'consequatur': u'Sint voluptatum quo.'}
- pyfloat:
  5.427466
- pyint:
  5831
- pyiterable:
  [u'Praesentium atque.', 510, u'Voluptatem.', u'Aspernatur culpa.', -86872010066.1, Decimal('1.39045051271E+12'), u'Aut neque quod quis.', 774237663.8, u'Libero voluptates.']
- pylist:
  [u'Enim voluptatem.', u'In ut unde aut est.', 3744, u'Tenetur harum nam.', u'Amet nam quam.', Decimal('-2.15222088569E+13'), 56014295154.367]
- pyset:
  set([2144, u'Est voluptas rem.', datetime(1989, 2, 18, 3, 52, 13), u'Est nihil.', Decimal('-243.7196'), datetime(1983, 9, 28, 12, 52, 56), u'beverlee76@yahoo.com', Decimal('-3.04622164413E+12'), u'Natus ut atque.'])
- pystr:
  Ex non explicabo.
- pystruct:
- pytuple:
- random_digit:
  5
- random_digit_not_null:
  1
- random_digit_not_null_or_empty:
  
- random_digit_or_empty:
  9
- random_element:
  b
- random_int:
  3804
- random_letter:
  x
- random_number:
  981
- randomize_nb_elements:
  11
- rgb_color:
  63,125,116
- rgb_color_list:
- rgb_css_color:
  rgb(21,8,176)
- safari:
  Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1 like Mac OS X; en-US) AppleWebKit/533.9.6 (KHTML, like Gecko) Version/3.0.5 Mobile/8B112 Safari/6533.9.6
- safe_color_name:
  fuchsia
- safe_email:
  irvin.little@example.net
- safe_hex_color:
  #dd7700
- secondary_address:
  Suite 378
- seed:
  None
- sentence:
  Consequuntur unde quo non voluptas minima voluptatibus.
- sentences:
  [u'Sapiente quia incidunt porro dolorum sapiente.', u'Et quaerat ad nesciunt maiores.', u'Ut excepturi autem qui laboriosam.']
- set_formatter:
- sha1:
  aab5c833e76265e48aa35b5b39ed798b2d21d971
- sha256:
  d74cbb45b74394c6a95f55f27926db1bdfeaf42dbbfcb3fddff22911f0dd4202
- simple_profile:
  {'username': u'cbuckridge', 'name': u'Britta Cartwright', 'birthdate': '1974-08-05', 'sex': 'M', 'address': u'123 Talia Island\nSouth Thursa, DC 68141', 'mail': u'vonda67@hotmail.com'}
- slug:
  ut-ducimus-illum
- ssn:
  142-04-9440
- state:
  Vermont
- state_abbr:
  VT
- street_address:
  33334 Auer Via
- street_name:
  Tayler Pines
- street_suffix:
  Curve
- suffix:
  II
- suffix_female:
  DVM
- suffix_male:
  V
- text:
  Eius ut atque voluptatum deserunt similique aliquid. Rerum quo commodi cum eius.
- time:
  14:45:00
- time_delta:
  16412 days, 22:34:37
- timezone:
  Asia/Saigon
- tld:
  com
- unix_time:
  330977642
- uri:
  http://boyer.com/main/index.php
- uri_extension:
  .html
- uri_page:
  post
- uri_path:
  tags/posts
- url:
  http://www.hammes.com/
- user_agent:
  Mozilla/5.0 (compatible; MSIE 7.0; Windows 98; Trident/4.0)
- user_name:
  jenkins.layton
- uuid4:
  8fef0d23-2010-44f1-873a-49767169db27
- windows_platform_token:
  Windows 95
- word:
  omnis
- words:
  [u'neque', u'odit', u'dolorum']
- year:
  1975
- zipcode:
  77130
- zipcode_plus4:
  71629-5918

Test that the correct template was used in a view function when testing with RequestFactory in Django

Django has a special assertion method for that purpose:
        with self.assertTemplateUsed("agents/incoming_queue.html"):
            response = incoming_queue(self.request)

Test context of the rendered template with RequestFactory in Django

When writing tests for the Django's view functions I prefer to use RequestFactory instead of the django test client. Tests that use RequestFactory are easier to understand and they are faster. For example, you need to test a simple view function:
def incoming_queue(request):
    if request.method == "POST":
        pass
    else:
        incoming_queue_list = UsageHistory.objects.filter(company=request.user.agent.company, queued=True)
        context = {
            "incoming_queue_list": incoming_queue_list,
            "page": "queue",
            "agent_available_url": reverse("agent_available")
        }
        return render(request, 'agents/incoming_queue.html', context)
If you want to test the context of the rendered template, it is easy to do with django test client as it attaches it to the response. If you want to use RequestFactory for that purpose, there is no easy way to do it. It would be comfortable to have something like assertTemplateContextIn(expected_context) method, that checks that expected_context was used during the template rendering. The following code was inspired by assertTemplateUsed method:
from copy import copy

from django.db.models.query import QuerySet
from django.test.signals import template_rendered
from django.test.utils import ContextList


class TemplateContextTestCase(object):
    def assertTemplateContextIn(self, expected_context=None):
        """
        Asserts that the template was rendered with the context that includes
        expected_context. Example:
            with self.assertTemplateContextIn(expected_context):
                vuew_function(self.request)
        """
        return _AssertTemplateContext(self, expected_context)


class _AssertTemplateContext(object):
    def __init__(self, test_case, expected_context):
        self.test_case = test_case
        self.expected_context = expected_context
        self.context = ContextList()

    def on_template_render(self, sender, signal, template, context, **kwargs):
        self.context.append(copy(context))

    def test(self):
        missing = []
        mismatched = []
        for key in self.expected_context.keys():
            if key in self.context:
                if self.context[key] != self.expected_context[key]:
                    match = False
                    # Compare QuerySets
                    if isinstance(self.context[key], QuerySet) and isinstance(self.expected_context[key], QuerySet):
                        if self.context[key].model == self.expected_context[key].model:
                            if list(self.context[key].values_list("id", flat=True)) == \
                               list(self.expected_context[key].values_list("id", flat=True)):
                                match = True
                    if not match:
                        mismatched.append(key)
            else:
                missing.append(key)
        return missing, mismatched

    def __enter__(self):
        template_rendered.connect(self.on_template_render)
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        template_rendered.disconnect(self.on_template_render)
        if exc_type is not None:
            return

        missing, mismatched = self.test()
        message = ""
        if missing:
            message = message + "Missing keys: " + ", ".join(x for x in missing) + "\n"
        if mismatched:
            for item in mismatched:
                message = message + "Context key mismatch '%s': %s != %s \n" % (
                    item, self.expected_context[item], self.context[item]
                )
        if message:
            self.test_case.fail(message)
We ofthen pass querysets instances to the context of the rendered template. The code above checks if 2 QuerySets are the same by comparing their models and ids of the elements. TemplateContextTestCase class can be used to extend TestCase class:
from django.test import TestCase, RequestFactory

from yourapp.tests.helpers import TemplateContextTestCase
from django.core.urlresolvers import reverse


class TestIncomingQueue(TestCase, TemplateContextTestCase):
    def test_context(self):
        agent = AgentFactory()
        self.request.user = agent.user
        expected = {
            "page": "queue",
            "agent_available_url": reverse("agent_available"),
            "incoming_queue_list": UsageHistory.objects.none()
        }
        with self.assertTemplateContextIn(expected):
            incoming_queue(self.request)

Monday, February 20, 2017

Show raw SQL queries in PostgreSQL

If you want to inspest what queries exactly Django ORM sends to the PostgreSQL, you can do it with postgres logging. The first step is to enable logging. Add
log_statement = 'all' 
to the file:
sudo vim /etc/postgresql/9.4/main/postgresql.conf
Then you are able to see raw SQL queries with command:
sudo tail -f /var/log/postgresql/postgresql-9.4-main.log 

Monday, February 6, 2017

curl: Prettify json output

Intsall jq package:
sudo dnf install jq
Usage example:
curl -u key:x "https://api.com/users.json" | jq

Monday, January 2, 2017

fedora 25: Replace xflux with redshift

xflux does not work with new fedora version any more (and likely will never do). Redshift is a good replacement in this case. It supports different methods to change color temperature of the screen and can use system location service to determine the location. Install redshift:
sudo dnf install redshift
There is a GUI for the application, but there is no need to install it as no configuration is needed. To make redshift start during the system load, you need to create a file /home/jsn/.config/autostart/redshift.desktop (where jsn is your username) with the following content:
[Desktop Entry]
Type=Application
Name=redshift
Comment=Redshift
Exec=/usr/bin/redshift
Terminal=false

Friday, October 28, 2016

How to set custom time and date on virtual machine

If your virtual machine is managed by VirtualBox, there are 2 services which synchronize date and time. The first step is to stop them from restoring the time:
sudo service systemd-timesyncd stop
sudo service vboxadd-service stop
After that you can set time with date command, for example:
sudo date +%T -s "00:12:00"
or
date -s "27 OCT 2016 00:12:00"
or
date +%Y%m%d -s "20161027"

systemd: Create a service

Example of the service configuration file `selenium_hub.service`:
[Unit]
Description=Selenium hub

[Service]
Environment=DISPLAY=:99
ExecStart=/bin/bash -c 'java -jar /opt/selenium/selenium-server-standalone.jar -role hub'
User=root

[Install]
WantedBy=multi-user.target
Place this file to /etc/systemd/system/ (symlinking won't work) and refresh available services:
sudo systemctl daemon-reload
Now it is possible to start the service with command:
sudo service selenium_hub status
You can also make it start when a system starts by executing one of the following commands:
sudo chkconfig selenium_hub on
sudo systemctl enable selenium_hub.service

Wednesday, October 19, 2016

Overwrite response body with mitmproxy

It is possible to run python script with mitmproxy. For example:
mitmproxy -s "modify_response_body.py"
The modification process is very simple. Take a look at the modify_response_body.py code:
from mitmproxy.models import decoded


def response(context, flow):
    if "site.custom.min.js" in flow.request.path:
        with decoded(flow.response):  # automatically decode gzipped responses.
            flow.response.content = flow.response.content.replace(
                "surfly.com",
                "sitesupport.net")
The script will look for a request with path that contains site.custom.min.js and replace all occurences of surfly.com with sitesupport.net

mitmproxy and websocket connections

mitmproxy does not really supports websocket connections. However, there is a workaround: it is possible to just ignore them. For example all your websocket conections are encrypted and go to the special subdomain:
mitmproxy --ignore ws.sitesupport.net:443

Thursday, October 13, 2016

Slow performance and no sound with pulseaudio-equalizer

I installed pulseaudio-equalizer on my laptop, but after 3 days my laptop became slow and there wes no sound at all. It happened because of the pulseaudio-equalizer package. Even if you remove it, the problem won't go because it adds some configuration to the pulseaudio itself and doesn't remove it.
Open pulseaudio configuration file, find pulseaudio-equalizer section and remove it completely:
sudo nano ~/.pulse/default.pa
The section should look like this:
### Generated from: pulseaudio-equalizer
load-module module-ladspa-sink sink_name=ladspa_output.mbeq_1197.mbeq master=alsa_output.pci-0000_05_00.0.analog-stereo plugin=mbeq_1197 label=mbeq #control=-0.2,-0.2,-0.2,-0.2,3.5,3.5,3.5,3.5,3.5,3.5,3.5,2.5,2.5,0.0,0.0
set-default-sink ladspa_output.mbeq_1197.mbeq
set-sink-volume alsa_output.pci-0000_05_00.0.analog-stereo 65536
set-sink-mute alsa_output.pci-0000_05_00.0.analog-stereo 0
### END: Equalized audio configuration
Reboot your computer and enjoy restored performance and sound!

Monday, October 10, 2016

fedora: Install latest VirtualBox

The latest virtualbox can be installed from the Oracle repository. First of all we need to install oracle repository:
cd /etc/yum.repos.d/
sudo wget http://download.virtualbox.org/virtualbox/rpm/fedora/virtualbox.repo
Install dependencies:
sudo dnf install binutils gcc make patch libgomp glibc-headers glibc-devel kernel-headers kernel-PAE-devel dkms
Install virtualbox. Note: pointing 5.1 is important as at the moment that is how it is called in the oracle's repository:
sudo dnf install VirtualBox-5.1
You might need to rebuild kernel modules with command:
sudo /usr/lib/virtualbox/vboxdrv.sh setup
And add current user to the xboxusers group:
sudo usermod -a -G vboxusers user_name
I had a problem reconfiguring kernel modules on my laptop. The error wasn't indicating anything specific. The problem was in the BIOS settings. Secure Boot should be disabled to allow module reconfiguration.