SCP from Linux to Windows

This is the scp command that copies a file from Linux to Windows:

scp -C -P {port} {file path on linux} USERNAME@IPADDRESS:mydir\\mysubdir\\filename

The trick is to use \\ in the Windows path. The flag -C compresses the file.

 

Advertisements

Python Mock Functions Not Being Called

Are you using mock to mock some functions during testing and mysteriously your tests are ignoring the mock decorator?

One way this can happen is if the function being mocked is either defined in the module that is being tested or is imported into the module being tested. How to get around this?

In my case, after I wasted time figuring out why mock was not working, I ended up modifying the code in my module so that I did not need mock. In the end, I think the modified code is better anyway. Often making code testable, makes it better too.

Numpy set_printoptions is not Working

Are you trying to use numpy.set_printoptions to format how arrays are printed and it does not seem to be working? Try checking the array dtype.

In my case, I was using a ufunc to apply a function to every element in the array. When I printed the result, I got a bunch of floating point numbers. When I tried to use numpy.set_printoptions to make the output a little more readable, it did not work. Further investigation showed that my array was now dtype “object”, not dtype “float64” as the original array. Converting the array solved the problem:

y = my_ufunc(x).astype(numpy.float64)

Working in Python 3.6 in Ubuntu 14.04

This link shows how to install python 3.6 on Ubuntu 14.04: https://askubuntu.com/questions/949638/installation-of-python3-6-2-on-ubuntu-14-04-python3-version-still-shows-3-4

When installing python 3.6 you will get a warning about not removing python 3.5. The commands above will not remove 3.5.

To run python 3.6, type:

/usr/bin/python3.6

In python 3.6, the pyvenv command for making virtualenvs was deprecated. The new command is:

python3.6 -m venv full-path-to-venv-dir

When I run that command, I get an error:

returned non-zero exit status 1

although the virtualenv folder is created along with a bunch of folders and files. Running the command like this works:

python3.6 -m venv full-path-to-venv-dir --without-pip

The virtual env can be activated with:

source path-to-env/bin/activate

After you activate the virtual env, you can install pip inside it, by downloading it and running it with the virtual env version of python:

wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

Testing Django When Using @cached_property

I use the @cached_property decorator quite a bit. It’s pretty straightforward. Usually, it’s set it and forget it. As noted in the docs, it persists as long as the instance persists.

However, it can cause problems during testing if you want to change it’s value. Here is how to change the value (from SO):

class SomeClass(object):

    @cached_property
    def expensive_property(self):
         return datetime.now()

obj = SomeClass()
print obj.expensive_property
print obj.expensive_property # outputs the same value as before
del obj.expensive_property
print obj.expensive_property # outputs new value

Django, Ajax and HTML Select

This happens all the time; one field in a form determines the options in another select field. One way to handle this is to do a Ajax post. It’s not difficult, but there are lots of parts to remember. Here is one way to do it (using jquery).

The Django Ajax handler:

from django.http import JsonResponse

def get_options(request):
    project_id = int(request.POST['project_id'])
    project = models.Project.objects.get(id=project_id)

    choices = get_select_choices(project)
    options = []
    for choice_id, choice_label in choices:
        option = '<option value="{}">{}</option>'.format(str(choice_id), choice_label)
        options.append(option)
    return JsonResponse({'options': options})

The javascript

<script type="text/javascript">
    var project_field, phase_select;

    var get_phases_for_project = function(){
        var project = project_field.val();

        if (project === ""){
            phase_select.empty();
            phase_select.append($("<option></option>").attr("value",'').text('--------------'));
        }
        
        $.post(
            "{% url 'my_url' %}",
            {project_id: project, csrfmiddlewaretoken: '{{ csrf_token }}'},
            /**
             * @param data
             * @param data.phases
             */
            function(data){
                phase_select.empty();
                $.each(data.phases, function (index2, value) {
                        phase_select.append(value);
                });
            }
        )
    };

    $(document).ready(function(){
        project_field = $('#id_project');
        project_field.change(get_phases_for_project);
        phase_select = $("#id_phase");
    });
</script>

SSL, Django Development Server and Chrome

I am developing a Django site that uses Stripe. Even for testing, Stripe requires HTTPS. In the past, I used django-sslserver version 0.19 and ignored the complaining Chrome made about the certificate being self signed. Today (Sept 2017), none of that worked.

First thing I did was upgrade django-sslserver to 0.20. This crashed with an error related to:

ssl.PROTOCOL_TLSv1_2

It turns out ssl is built into Python and that constant is not defined in version 2.7.6. Reverting back to django-sslserver to 0.19 solved that problem.

Next, Chrome/Stripe will no longer let you ignore the SSL certificate warnings. This blog post by Alexander Zeitler does a pretty good job explaining how solve this problem. If you run into this problem:

error on line -1 of /dev/fd/11
140736435860488:error:02001009:system library:fopen:Bad file descriptor:bss_file.c:175:fopen('/dev/fd/11','rb')
140736435860488:error:2006D002:BIO routines:BIO_new_file:system lib:bss_file.c:184:
140736435860488:error:0E078002:configuration file routines:DEF_LOAD:system lib:conf_def.c:197:

remove sudo from createselfsignedcertificate.sh and run the script using sudo.

When all of that is done, you need to tell Chrome to trust your Certificate Authority by going to “Advanced Settings -> Manage Certificates”, then “Authorities/Import. Select the rootCA.pem in the ssl directory created by the scripts above.

This probably already setup on your machine, but you need to check the file /etc/hosts to make sure localhost points to the IP address django-sslserver is using (most likely 127.0.0.1). Then in the browser go to:

https://localhost:8000/

Launch django-sslserver using something like:

python manage.py runsslserver --certificate ~/ssl/server.crt --key ~/ssl/server.key