Programming languages

How to parse filename extension from URL using Python

If you have an URL like

https://logodix.com/logo/1667872.jpg?param=value

and you want to find just the filename extension (.jpg for this example), use the following code:

from urllib.parse import urlsplit
import os.path

url = "https://logodix.com/logo/1667872.jpg?param=value"

path = urlsplit(url).path
extension = os.path.splitext(path)[-1] # e.g. ".jpg"

 

Posted by Uli Köhler in Python

How to fix Python 3 AttributeError: ‘function’ object has no attribute ‘urlsplit’

Problem:

When trying to urlsplit an URL in Python 3:

from urllib.parse import urlparse

path = urlparse.urlsplit(remote_image_url).path

you see the following error message:

AttributeError                            Traceback (most recent call last)
Input In [30], in <cell line: 3>()
      1 from urllib.parse import urlparse
----> 3 path = urlparse.urlsplit(remote_image_url).path
      4 filename = posixpath.basename(path)

AttributeError: 'function' object has no attribute 'urlsplit'

Solution:

The equivalent of urlparse.urlsplit() in Python 3 is urllib.parse.urlsplit().

Therefore, a working code example is

from urllib.parse import urlsplit

path = urlsplit(remote_image_url).path

 

Posted by Uli Köhler in Python

How to fix Python 3 ModuleNotFoundError: No module named ‘urlparse’

Problem:

While trying to import urlparse in Python 3 using

import urlparse

you see the following error message:

---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Input In [29], in <cell line: 1>()
----> 1 import urlparse

ModuleNotFoundError: No module named 'urlparse'

Solution:

In Python 3, urlparse has been renamed to urllib.urlparse. In order to import it, use this line instead:

from urllib.parse import urlparse

 

Posted by Uli Köhler in Python

How to fix Angular NullInjectorError: No provider for HttpClient!

In case you see the following error for your Angular application in your JS console:

main.ts:6 ERROR NullInjectorError: R3InjectorError(AppModule)[MyService -> HttpClient -> HttpClient -> HttpClient]: 
  NullInjectorError: No provider for HttpClient!
    at NullInjector.get (core.mjs:7599:27)
    at R3Injector.get (core.mjs:8020:33)
    at R3Injector.get (core.mjs:8020:33)
    at R3Injector.get (core.mjs:8020:33)
    at injectInjectorOnly (core.mjs:634:33)
    at Module.ɵɵinject (core.mjs:638:60)
    at Object.MyService_Factory [as factory] (my.service.ts:8:38)
    at R3Injector.hydrate (core.mjs:8121:35)
    at R3Injector.get (core.mjs:8009:33)
    at ChainedInjector.get (core.mjs:12179:36)

you need to add HttpClientModule to your app.module.ts.

First, import HttpClientModule at the top of app.module.ts:

import { HttpClientModule } from '@angular/common/http';

After that, add

HttpClientModule,

to the imports: [...] section of your @NgModule, for example:

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    HttpClientModule,
    BrowserModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

After that, your error should have disappeared

Posted by Uli Köhler in Angular, Typescript

Angular HttpClient JSON service minimal example

Using Angular’sHttpClient  in a service to fetch a JSON is pretty straightforward. In this example, we’ll fetch a JSON array.

Note that it’s recommended to create your own TypeScript interface for improved static typing, but nevertheless starting with any[] is often a good idea since it allows you to get started quickly.

public loadMyJSONArray(): Observable<any[]> {
  return this.http.get<any[]>(`/api/my-api`);
}

Full service example

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class MyService {

  constructor(private http: HttpClient) {
  }

  public loadMyJSONArray(): Observable<any[]> {
    return this.http.get<any[]>(`/api/my-api`);
  }

}

 

 

Posted by Uli Köhler in Angular, Typescript

How to auto-restart bottle server when Python file changes using nodemon

Assuming you have a Python script server.py that you want to auto-reload every time the file changes, use the following script using nodemon:

nodemon -w . --exec python server.py

The -w . tells  nodemon files to watch for changes of all files in the current directory (.)

I generally recommend creating a script start.sh to automatically run this command:

#!/bin/sh
nodemon -w . --exec python server.py

and then make it executable using

chmod a+x start.sh

Now you can run it using

./start.sh

 

Posted by Uli Köhler in Python

How to return JSON array using bottle – minimal example

Returning a JSON array in bottle involves setting the response content type to application/json and then manually dumping the array using json.dumps():

#!/usr/bin/env python3
from bottle import route, run, response
import json

@route('/')
def json_array():
    response.content_type = 'application/json'
    return json.dumps(["a", "b", "c"])

run(host='localhost', port=9000)

 

Posted by Uli Köhler in Python

How to auto-restart bottle server when Python file changes using entr

Note: I do not recommend using entr any more since for me it doesn’t work reliably. I recommend using nodemon instead, see How to auto-restart bottle server when Python file changes using nodemon

Assuming you have a Python script server.py that you want to auto-reload every time the file changes, use the following script using entr:

ls *.py | entr python server.py

The ls *.py tells entr which files to watch for changes.

Posted by Uli Köhler in Python

Bottle HTTP server with dedicated server class – minimal example

This script uses a dedicated class MyServer to encapsulate the bottle server appropriately. Compared to our previous post Python bottle minimal example it provides better encapsulation of the server at the cost of slightly more lines of code.

#!/usr/bin/env python3
from bottle import Bottle, run

class MyServer(object):
    def __init__(self):
        self.app = Bottle()
        self.init_routes()
        
    def init_routes(self):
        """Initialize all routes"""
        @self.app.route('/hello')
        def hello():
            return "Hello World!"

    def run(self):
        run(self.app, host='0.0.0.0', port=8080)
        
# Example usage
if __name__ == "__main__":
    server = MyServer()
    server.run()

How to use

Run the server

python bottle-server.py

and open

http://localhost:8080/hello

Now you should see the Hello World! message.

Posted by Uli Köhler in Python

Inventree Python API: How to list all stock locations

See our previous post Inventree Python API: Minimal API connect example using YAML config for our method of creating the api object using a YAML config file!

from inventree.stock import StockLocation

all_stock_locations = StockLocation.list(api)

# Dict of part categories by name
# (e.g. 'OpAmps')
stock_locations_by_name = {
    category["name"]: category
    for category in all_stock_locations
}
# Dict of part categories by public key (e.g. 7)
part_locations_by_pk = {
    category.pk: category
    for category in all_stock_locations
}
# Dict of part categories by hierarchical path
# (e.g. 'Office/Spart parts box')
stock_locations_by_pathstring = {
    category.pathstring: category
    for category in all_stock_locations
}

 

Posted by Uli Köhler in InvenTree, Python

Inventree Python API: How to create a new part

See our previous post Inventree Python API: Minimal API connect example using YAML config for our method of creating the api object using a YAML config file!

The following code finds a part category called ICs and creates a new part in that category.

First, we need to fetch the part categories, this is from our previous post Inventree Python API: Minimal API connect example using YAML config:

from inventree.part import PartCategory

all_categories = PartCategory.list(api)

# Dict of part categories by name
# (e.g. 'OpAmps')
part_categories_by_name = {
    category["name"]: category
    for category in all_categories
}
# Dict of part categories by public key (e.g. 7)
part_categories_by_pk = {
    category.pk: category
    for category in all_categories
}
# Dict of part categories by hierarchical path
# (e.g. 'Electronics-Components/ICs/OpAmps')
part_categories_by_pathstring = {
    category.pathstring: category
    for category in all_categories
}

Now let’s select the correct category:

ics = part_categories_by_name['ICs']

Now it’s finally time to create the part:

from inventree.part import Part

new_part = Part.create(api, {
    'name': 'L78L33ABD',
    'description': '100mA 3.3V fixed LDO regulator, SOIC-8',
    'category': ics.pk
})

You can read the primary key (pk) for the newly generated part using

new_part.pk
Posted by Uli Köhler in InvenTree, Python

Inventree Python API: How to list all part categories

See our previous post Inventree Python API: Minimal API connect example using YAML config for our method of creating the api object using a YAML config file!

from inventree.part import PartCategory

all_categories = PartCategory.list(api)

# Dict of part categories by name
# (e.g. 'OpAmps')
part_categories_by_name = {
    category["name"]: category
    for category in all_categories
}
# Dict of part categories by public key (e.g. 7)
part_categories_by_pk = {
    category.pk: category
    for category in all_categories
}
# Dict of part categories by hierarchical path
# (e.g. 'Electronics-Components/ICs/OpAmps')
part_categories_by_pathstring = {
    category.pathstring: category
    for category in all_categories
}

Note that this code by itself does not take into account the hierarchy of the categories.

Example output

part_categories_by_name:

{'Elektronik-Komponenten': <inventree.part.PartCategory at 0x7fd735125510>,
 'ICs': <inventree.part.PartCategory at 0x7fd7356d1720>,
 'OpAmps': <inventree.part.PartCategory at 0x7fd735ead4e0>}

part_categories_by_pk:

{1: <inventree.part.PartCategory at 0x7fd7346b5db0>,
 2: <inventree.part.PartCategory at 0x7fd73438aa10>,
 3: <inventree.part.PartCategory at 0x7fd727325b40>}

part_categories_by_pathstring:

{'Elektronik-Komponenten': <inventree.part.PartCategory at 0x7fd727bd3040>,
 'Elektronik-Komponenten/ICs': <inventree.part.PartCategory at 0x7fd727bd1db0>,
 'Elektronik-Komponenten/ICs/OpAmps': <inventree.part.PartCategory at 0x7fd727bd1060>}

 

Posted by Uli Köhler in InvenTree, Python

Inventree Python API: Minimal API connect example using YAML config

This example allows you to create a config file inventree.yml:

server: 'https://inventree.mydomain.com'
username: 'admin'
password: 'Chuiquu5Oqu8il5ahLoja4aecai4ee'

and then read it in Python and connect to the Inventree API:

from inventree.api import InvenTreeAPI

# Load config
import yaml

with open("inventree.yml", "r") as file:
    config = yaml.safe_load(file)
    
api = InvenTreeAPI(config["server"], username=config["username"], password=config["password"])

 

Posted by Uli Köhler in InvenTree, Python

FreeRTOS task queue with static memory (xQueueCreateStatic) minimal example

Also see our previous post FreeRTOS task queue minimal example which also has examples for how to send & receive with a queue. The post you’re currently viewing is just about xQueueCreateStatic()

enum class MQTTTaskType : uint8_t {
    SendStatus = 0,
    SendInfo
};

// This struct will be inserted into the queue
struct MQTTTask {
    MQTTTaskType task; // The type of work that is requested from the received
    // TODO add your custom fields here if requred
};

constexpr size_t MQTT_TASK_QUEUE_LENGTH = 6;
static QueueHandle_t mqttTaskQueue;
static StaticQueue_t mqttTaskQueueStatic;
static uint8_t mqttTaskQueueStorageArea[ MQTT_TASK_QUEUE_LENGTH * sizeof(MQTTTask) ];

void setup() {
    // Create task queue
    mqttTaskQueue = xQueueCreateStatic( MQTT_TASK_QUEUE_LENGTH,
                                 sizeof(MQTTTask),
                                 mqttTaskQueueStorageArea,
                                 &mqttTaskQueueStatic );
}

 

Posted by Uli Köhler in C/C++, Embedded, FreeRTOS, PlatformIO

How to fix GCC error: unknown type name ‘size_t’ (STM32)

Problem:

When you try to compile your C/C++ project (typically a STM32 project):

C:/Users/User/MyProject/MyHeader.h:9:7: error: unknown type name 'size_t'
    9 | const size_t MySize = 15;
      |       ^~~~~~

Solution:

At the top of the file where this error occurs, add the following line:

#include <stddef.h>

 

Posted by Uli Köhler in C/C++, GCC errors, STM32

PySerial minimal RFC2217 example: Copy data received from serial port to stdout

Also see the same example for a local serial port: PySerial minimal example: Copy data received from serial port to stdout

This example connects to the RFC2217 remote serial port on 10.1.2.3 port 1234. It does not send data to the serial port but only copies data received from the serial port to stdout.

#!/usr/bin/env python3
import serial
with serial.serial_for_url("rfc2217://10.1.2.3:1234", baudrate=115200) as ser:
    try:
        while True:
            response = ser.read()
            if response:
                print(response.decode("iso-8859-1"), end="")
    finally:
        ser.close()

 

By using iso-8859-1   decoding, we ensure that even binary bytes are decoded in some way and do not cause an exception.

Posted by Uli Köhler in Embedded, Python

How to install .NET Core SDK on Ubuntu 22.04

wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
sudo apt-get update && sudo apt-get install -y dotnet-sdk-7.0

Source for these commands: Microsoft documentation

Posted by Uli Köhler in C#, Linux

How to download forum pages to HTML using Python & requests

This will download page 1000 … page 1 in descending order and save the HTML to 1000.html up to 1.html

import requests
for i in range(1000, 0, -1):
    with open(f"{i}.html", "w") as outfile:
        outfile.write(requests.get(f"https://forum.my-domain.com/showthread.php?123456-my-thread/page{i}").text)

With progress bar

import requests
from tqdm import tqdm
for i in tqdm(range(1000, 0, -1)):
    with open(f"{i}.html", "w") as outfile:
        outfile.write(requests.get(f"https://forum.my-domain.com/showthread.php?123456-my-thread/page{i}").text)

 

Posted by Uli Köhler in Python

How I fixed PlatformIO Arduino portGET_ARGUMENT_COUNT() result does not match for 0 arguments

Problem:

When trying to compile your Arduino PlatformIO project, you see multiple error messages like the following.

In file included from /home/uli/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/sys-include/stdlib.h:19,
                 from /home/uli/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/include/c++/8.4.0/cstdlib:75,
                 from /home/uli/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/include/c++/8.4.0/stdlib.h:36,
                 from /home/uli/.platformio/packages/framework-arduinoespressif32/cores/esp32/WString.h:26,
                 from /home/uli/.platformio/packages/framework-arduinoespressif32/cores/esp32/Print.h:26,
                 from /home/uli/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src/WiFi.h:27,
                 from /home/uli/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src/WiFi.cpp:24:
/home/uli/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/port/xtensa/include/freertos/portmacro.h:717:41: error: static assertion failed: portGET_ARGUMENT_COUNT() result does not match for 0 arguments
 _Static_assert(portGET_ARGUMENT_COUNT() == 0, "portGET_ARGUMENT_COUNT() result does not match for 0 arguments");

Solution:

For me, the solution was as follows. I had

build_flags = --std=c++17

in my platformio.ini. Replacing it by

build_flags = --std=gnu++17

fixed the issue for me.

Posted by Uli Köhler in Arduino, C/C++, PlatformIO