## Getting MX Linux Samba to work naturally with Windows Network

I normally disable “Computer Browser” service in Windows by default because multiple computers having it on causes errors showing up in event log complaining there are multiple masters, and it’s not necessary for my simple home network because I’m just using a workgroup (no domain controller).

However, today I found out that even after setting up MX Linux’s Samba correctly (see below), if none of the computers on my windows network runs “Computer Browser”, my Windows computer name will not show up in “Thunar File Manager” although I can access it with smb://, and linux computers running Samba server shows up fine.

There’s also another twist to get the SMB client to work in Thunar File Manager. Despite smbtree works right out of the box (it detects the Windows shares), I’ll have to add this line in /etc/samba/smb.conf for the file manager to even probe the list of computers (not timeout):

name resolve order = bcast host

The point is to use broadcast lookup BEFORE dns lookup. DNS lookups for my local resources are often temperamental (could it be my router?), and I saw Linux Mint working with Windows briefly without these settings (editing smb.conf and also enabling “Computer Browser” service in Windows), but it failed today even after I re-installed MX Linux from scratch.

The other lines mentioned like client max protocol = NT1 and netbios name mentioned on the forums are not needed.

After configuring it. Restart smbd:

sudo /etc/init.d/smbd restart

7,047 total views

## Spyder on MX Linux

This is another example that non-commercial (open-source) Linux/Python does not have a feel of a finished product: things break out of the box when installed fresh, in the most simple, expected ways, without any tweaks.

Again, don’t get me wrong, open-source free software are good stuff (more modern concepts and people working on it for free), but it’s never going to beat professional companies (like Microsoft/MATLAB) in how well-funded they are so they can maintain their software and the user experience using their profits. So far, users are still expected to put up with a bunch of unjustifiably unnecessary work to get to where they want to go with community-maintained software like Linux/Python.

This time I’m installing Spyder on MX Linux. Look at how many damn hoops I have to jump to get Spyder 3 to function properly there:

1. I installed python3-spyder from MX Package Installer
2. Spyder complained about missing rope on start
3. Installed python-rope on MX Package Installer. The complaint still won’t go away
4. I tried follow the instruction sudo pip3 install rope_py3k  and realized pip3 was not installed already with the Python that came with Spyder! (Didn’t have the problem with the Windows counterpart).
5. Installed python3-pip from MX Package Installer.
6. Came back and run pip3 install rope_py3k. It choked at "Command 'python  setup.oy egg_info' failed with error code 1 in /tmp/pip-build-0nnknjhi/rope-py3k". Again, known problem.
7. Followed the solution in the comments pip3 install --upgrade setuptools
8. Then come back and run pip3 install rope_py3k again. It says "Failed building wheel for rope-py3k" in between, but nonetheless I’ll try to move on since it says "Successfully installed rope-py3k-0.9.4.post1"

Then Spyder launch uneventfully.

These are not design decisions (sacrificing one quality for another), but inter-operability wrinkles that nobody are paid enough to do the grunt-work babysitting it. So if your business profits heavily from it, consider sponsoring the developers!

It’s also slightly annoying that the version of Spyder maitained in MX Linux’s most recent repository is a little older than what’s actually available (3.1.3+dfsg1-3 instead of 3.3.4).

At first I followed instructions to have PIP to update it: pip3 install -U spyder, but it doesn’t work. I got a lot of “failed building wheel for (package)” error.

I also realized the Python that came with it is 3.5, not the 3.7(.3) I had in Windows. I checked the MX package manager and indeed it stopped at 3.5. After some searching, I learned the base system package was frozen in 2016! MX Test Repo (at your own risk) has Python 3.7 though.

807 total views

## Ubuntu to remember list – setup

Network

• Install samba. Use smb:// as URL
(MX Linux doesn’t need you to remember it. Windows computers and shares just shows up in File Manager right away!)

Extracting files

• Need to install unrar or the built-in Archive Manager will show “Unsupported error during extraction” and extract RAR files partially! WTF! It’s 2019! No wonder Microsoft is still making big bucks! (MX Linux is much better about this out of the box. Not only it works, I can just drag and drop the contents directly to the desktop while I cannot do it with Ubuntu!)

Internationalization

• Japanese fonts: sudo apt-get fonts-vlgothic
• Get Foobar2000 to show Japanese fonts: install the above and File->Preferences->Display->Colors and Fonts->Fonts-Playlists-> VL PGothic
• Need to log-off and re-login after installing Japanese Language Support (it’s not just for UI translation) before “Japanese (Mozc)” input option show up
• It’s a major pain in the butt to emulate the Ctrl+Space shortcut that switches between IMEs in Windows in Ubuntu, but in MX Linux, you can set it in “IBus Preferences”->Keyboard Shortcuts.

Routine software to install

• rdesktop / Remmina
• foobar2000 (Clementine player that came with MX Linux worked just as good. I chose foobar2000 to conserve resource in Ubuntu on a slow computer.)

558 total views

## Ubuntu to remember list – usage

Log off: Ctrl+Alt+Del -> Log off

Command Prompt (Terminal): Ctrl+Alt+T

Default application for file type: Right-Click->Properties->Open With Tab

ibus controls IME. Can fix problems with ibus restart

653 total views

## I see dead processor, the first time in my life I've dealt with hundreds if not thousands of PCs since I was a kid

Ever since I got my hands into assembling and troubleshooting PCs when I was a kid, both through my own experience and general consensus in the computer hobbyist community, CPU is almost the last thing to suspect at fault for a non-functioning computer, much less likely if:

• There are no signs physical damages (mechanical or heat stress)
• There were no shorts (burning electronic smells)
• There weren’t any extreme overclocking (at least Vcore was pumped)
• The computer used to boot, but has some random hangs

After 20+ years (and troubleshooted a few hundreds if not a couple of thousand PCs), today I encountered (actually zeroed-in that it’s the culprit) the first bad processor in my life. It was inside a M815G motherboard from a 54854A oscilloscope that I bought that wouldn’t boot into windows without random ‘file corrupted’ errors. Then after a few tries, the board wouldn’t even boot, not even any code on the POST card.

At first I suspected it’s an aging motherboard, since I checked the RAM and passes Memtest86+ on another board. It’d be either the motherboard or CPU, which I never considered it might be the CPU given how unlikely it is both by other people and myself.

I couldn’t be bothered to dig at the moment so I simply replaced the entire motherboard (with CPU and RAM installed) with another unit and confirmed that the 54854A I bought didn’t have any deeper problems. Then I put this ‘bad M815G motherboard’ on my back burner.

Today I was trying to revive a VP22 motherboard (which boots only if I apply pressure on certain areas of the PCB) that didn’t have the Fan+Heatsink+CPU+RAM. I happen to have a spare Pentium 3 and some PC-133 (SDRAM) lying around, but not the heatsink+fan, so I borrowed it from the M815G in the repair-if-I-feel-like-it pile.

The VP22 booted with pressure on the PCB (beeped, checked POST card) but I couldn’t see any display, so I thought of swapping-in the known-‘good’ CPU from the ‘faulty’ M815G to see if I had the wrong revision that the VP22 didn’t support. The VP22 used to get stuck in the boot process, but at least the POST card has a reading, this time after swapping in the CPU from the M815G, it has no POST code at all. No pulse.

I got suspicious and took the the CPU from the VP22 and put it in the ‘faulty’ M815G. Guess what? The M815G in question boots and runs fine!!! WTF! For all that time I thought my M815G has a difficult fault just because I had a marginally failing an then dead CPU, which I didn’t even consider the possibility given how unlikely the CPU is at fault.

And no, it’s not the thermal compound drying up, it’s freshly applied every time I move it to a different motherboard. The CPU was only used in M815G/VP22 which does not even have any means of overclocking. No burns or smells or physical damage, and the computer used to boot. The CPU just died of natural causes.

A black swan day!

675 total views

## Watch out for ‘const’ method in Python

One thing I feel a little bit not quite as intuitive when I switch to Python is I constantly have to look up whether the method directly updates the contents or it’ll return a different object (of the same type) that I’ll have to overwrite the input variable myself.

An example would be strings and bytes object. replace() sounded like an updating method, but it’s actually a ‘const’ method (a term borrowed from C++ to say that the method does not have side-effects) that does not change the state of the object.

I initially thought this has to do with whether the object is immutable or not, but I tried it on bytearray objects (which is mutable), replace() behaves consistently with the identically named methods in other immutable objects (bytes object, string object): you’ll need to assign the output to self (basically bind the name to the temporary and throw away the original).

bts = b'test'
bts.replace('es', 'oas')       # dumps the output to workspace (can be accessed by _) and do nothing else
bts = bts.replace('es', 'oas') # actually updates bts

563 total views

## Duracell leaks in original package before being used!

I knew Duracell is known for leaking when left in equipment for too long (too numerous to count: I had it leaked in wireless mouse, remote control, clocks, etc), but I always thought it’s my fault for leaving them in my electronics for a long time.

Today I got my answer: it’s not my fault that the batteries leaked. I just opened a new box of 4 AAA Duracells, and one of the new unused battery (the marking says it expires in 2023. It’s 2019 at the time of writing). I bought them from Tigerdirect so it’s likely to be genuine (on 10/2015). Here’s the pictures:

Not only I am not going to get Duracell batteries even if they are free, I’m going to toss all Duracell I have. It’s nothing but a menace. It’s worse than white label brands as it’s known to leak. It has to be a design or chemical formula or manufacturing process problem they have. By no means it’s an isolated incident.

829 total views

## Anonymous Functions (MATLAB) vs Lambdas (Python) Anonymous Functions in MATLAB is closure while Lambdas in Python are not

Lambdas in Python does not play by the same rules as anonymous functions in MATLAB

• MATLAB takes a snapshot of (capture) the workspace variables involved in the anonymous function AT the time the anonymous function handle is created, thus the captured values will live on afterwards (by definition a proper closure).
• Lambda in Python is NOT closure! [EDIT: I’ll need to investigate the definition of closure more closely before I use the term here] The free variables involved in lambda expressions are simply read on-the-fly (aka, the last state) when the functor is executed.

It’s kind of a mixed love-and-hate situation for both. Either design choice will be confusing for some use cases. I was at first thrown off by MATLAB’s anonymous function’s full variable capture behavior, then after I get used to it, Python’s Lambda’s non-closure tripped me. Even in the official FAQ, it address the surprise that people are not getting what they expected creating lambdas in a for-loop.

To enable capture in Python, you assign the value you wanted to capture to a lambda input argument (aka, using a bound variable as an intermediary and initialize it with the free variable that needs to be captured), then use the intermediary in the expression. For example:

lambda: ser.close()      # does not capture 'ser'
lambda s=ser: s.close()  # 'ser' is captured by s.

I usually keep the usage of nested functions to the minimum, even in MATLAB, because effectively it’s kind of a compromised ‘global’ between nested levels, or a little bit like protected classes in C++. It breaks encapsulation (intentionally) for functions in your inner circle (nest).

It’s often useful for coding up GUI in MATLAB quick because you need to share access to the UI controls within the same group. For GUI that gets more complicated, I actually avoided nested functions altogether and used *appdata() to share UI object handles.

Functors of nested functions are closures in both MATLAB and Python! Only Lambdas in Python behave slightly differently.

786 total views

## Handling resources that needs to be cleaned up in Python and MATLAB Files, sockets, ports, etc.

Using try/catch to handle resource (files, ports, etc) cleanup is out of fashion in both MATLAB and Python. In MATLAB, it uses a very slick idea based on closures to let you sneak your cleanup function (as a function object) into an onCleanup object that will be executed (in destructor) when that object is cleaned up by being out of scope.

Python does not provide the same mechanism. Instead, it relies on the resource class (like file IO or PySerial) to implement as a Context Manager (has __enter__) and provide the cleanup in the manager’s __exit__ method. Then you use the with keyword with the returned resource object put after as keyword, like this:

with File('test.txt', 'w') as f:
f.write('SPFCCsMfT!')

The body of with-block will not run (and therefore object f won’t be created) if the with-statement throws an exception. Unfortunately, it’s a fill-or-kill (or try/finally) instead of try/catch. So if the resource failed to open, resource object f is simply not created. No other clue is generated. This is what I hate about the with-statement. There are two ways to kind of get around it, but they are not reliable and might cause other bugs if you don’t keep track of the variable names in the local context:

1. Check for the existence of the resource object
if 'f' in dir(): del f   # Avoid name conflicts
with File() as f
print("Done");
if not 'f' in dir():
print('Cannot create file');
2. Use the body code to indicate that the with-block is executed
isSuccess = false     # Signaling
with File() as f
isSuccess = true
print("Done')
if not isSuccess
print("Cannot create file");


3. Back to the old way
try:
f = File();
except:
print("Cannot open file")
else:
cleanup_obj = onCleanup(lambda x = f: x.custom_cleanup())
# run core code that uses resource f


Actually there’s another mess here. In PySerial, creating the Serial object with a wrong port string will throw an exception as well, which with-as statements cannot handle. Therefore you’ll need to do both:

try:
ser = serial.Serial(dev_str)
except:
print(dev_str + " not accessible (either the wrong port of something else opened it)");
else:
with ser:
# meat

If your resource initializer does not have context manager built in, and you want a quick-and-dirty solution (given your cleanup is a one-liner). Use my library (lang.py) that recreates onCleanup():

"""
@author: [2019-04-23] Hoi Wong
"""
class onCleanup:
'''make sure you 'capture' the lambdas by initializing an intermediate running variable
e.g. lambda s=ser: s.close()
lambda: ser.close() will NOT work as ser is not 'captured''''
def __init__(self, functor):
def __del__(self):
self.task()

Then you can use the old way without nesting try/except:

try:
f = File()
except:
print("Cannot open file")
else:
cleanup_obj = onCleanup(lambda x = f: x.custom_cleanup())
# run core code that uses resource f

Check with the provider of your resource initializer to see if context manager is already implemented. Use onCleanup() only when you don’t have this facility and you don’t want to build a whole context manager (even with decorators) for a one-liner cleanup.

580 total views

## Programmatically determining platforms on MATLAB and Python

 MATLAB Python OS (32-bit or 64-bit) computer(‘arch’) platform.machine().endswith(’64’) Engine (32-bit or 64-bit) mexext() platform.architecture()[0].startswith(’64’); OS Type (Broad) ismac/isunix/ispc or computer() platform.system()

580 total views