Dell XPS 17: The Worst Support That Money Can Buy

Dell’s warranty process is an expensive ruse.

I have a Dell XPS 17, which has an 8-core 2.4GHz I9 CPU, 2TB SSD, 64GB memory, GeForce RTX 2060 GPU, and 17″ 4K screen in a very manageable 15″ package (very thin edges on the bezel). All of that power, and I still get about four or five hours on the battery as long as I am prudent with the screen brightness, fan, and attached accessories.

It has a good weight while still being very thin and having an efficient, medium-sized transformer block. I paid thirty-five hundred for it and several hundred more for the warranty. It is the most expensive laptop they carry. It is one of the most expensive laptops on the market. I am a very resource-intensive developer who is writing code for at least fifteen-hours on most days. I had just become sick of losing time due to insufficient resources. I wanted to have more space then I usually needed, more memory then I usually needed, and more speed then I normally needed, for once, while sticking to Linux (and just generally avoiding Apple).

Five months later, I noticed that I had somehow ended-up with the glass crushed at the bottom-right of my screen. I have no idea how it happened. Maybe uneven stresses on the glass near the hinge as I opened and closed the lid over time. Dell offered to send me a technician to replace the LCD. I remembered doing this in college several times (they would come to my dorm room) and I had had a good experience. That way I did not lose the laptop for a week or two while also avoiding the possibility of them insisting on replacing it before I had a chance to fully back it up. The technician was third-party, since Dell does not do it themselves. This might potentially add a layer of complexity but is otherwise fine.

The technician remarked about how densely-packed the laptop was, which led me to believe that he had never worked on any XPS before. The screen stopped working a few minutes after he left. It took another week for them to send another technician, whom never showed up. When their dispatch attempted to schedule another technician, they said that the previous technician had already claimed the box with the replacement screen, disappeared with it, and could not be found, so they had no part to send with another technician. It took me another two weeks to get another technician, who then fried my motherboard while he was installing the new screen.

I then spent several additional weeks of explaining and reexplaining the situation to their support department, which sucked over the phone, sucked over the website chat, and sucked slightly less via Whatsapp (it at least did not require me to keep the website open, and seemed to be a little more responsive). Every day, I got a different support person and a different manager from the other side of the planet. They would call me to confirm details, I would ignore their call because I would have no idea that one of the spam calls that I routinely got every day was actually Dell calling from India at 10pm, and there existed no way for me to return their phone calls. I was buried in bureaucracy. Finally, after telling me that they wanted to replace the whole laptop, they got an approval a week later. I had it within two or three days after that. Though, they ended-up sending me a refurbished laptop. It had a sticker on the bottom that said “refurbished”, which came apart when I tried to remove it. Awesome.

After the first week or two, I had ended-up buying an alternative, emergency high-end Lenovo laptop because I was a business owner who needed to travel and needed a functioning laptop. Dell was failing me on a pretty major level and I could not afford to be exposed to them ever again.

I had started with, basically, a new laptop, there was damage through normal usage that I could not be held responsible for, and I ended-up with a used laptop after losing a couple of months and part of my soul to their support process. Plus, I needed an extra high-end laptop from a competitor just to account for their incompetency in the future.

The XPS is a gorgeous laptop, with only the occasional touchpad problem, and yet the lack of respect Dell showed me both via their support process (an army of separate representatives and inexperienced support personnel) and quality of their warranty (refurbished replacement) makes it a terrible investment. A four-thousand dollar investment that my company depends on and no peace of mind to speak of.

Python: Substitute Values Into YAML During Load

There’s definitely a case to be made for automatically and efficiently applying environment variables or another set of replacements into a YAML-based config or set of instructions on load. This example uses PyYAML. We’ll use Python’s built-in string templating to replace tokens like “$NAME” with values from a dictionary. It will fail, as it should, if the name is not in the given dictionary.

import string
import yaml

def load_yaml(f, context):

    def string_constructor(loader, node):

        t = string.Template(node.value)
        value = t.substitute(context)

        return value

    l = yaml.SafeLoader
    l.add_constructor(',2002:str', string_constructor)

    token_re = string.Template.pattern
    l.add_implicit_resolver(',2002:str', token_re, None)

    x = yaml.load(f, Loader=l)
    return x

y = """\
aa: bb
cc: dd $EE ff

context = {
    'EE': '123',

d = waw.utility.load_yaml(y, context)


{'aa': 'bb', 'cc': 'dd 123 ff'}

Was It Actually Possible For A Nuclear Bomb/Explosion To Set The Atmosphere On Fire?

Actually, no. In summary, two of the reasons are that so much of the energy are lost into radiation and light.

It is shown that, whatever the temperature to which a section of the atmosphere may be heated, no self-propagating chain of nuclear reactions is likely to be started. The energy losses to radiation always overcompensate the gains due to the reactions.

It is impossible to reach such temperature unless fission bombs or thermonuclear bombs are used which greatly exceed the bombs now under consideration. But even if bombs of the required volume (i.e., greater than 1,000 cubic meters) are employed, energy transfer from electrons to light quanta by Compton scattering will provide a further safety factor and will make a chain reaction in air impossible.


If, after calculation, [Compton] said, it were proved that the chances were more than approximately three in one million that the earth would be vaporized by the atomic explosion, he would not proceed with the project. Calculation proved the figures slightly less — and the project continued.

In later studies, it was determined to actually be impossible.


Installing VMWare Remote Console (VMRC) On Arch/Manjaro

When you download the Remote Console bundle installer from VMWare and run it, the UI will start and simply fail with “Installation was unsuccessful” error. There is no console output, seems to be no log, and no apparent option to enable verbosity. Since I’m using Manjaro, I’d rather not use the package, which is only available in AUR.

A successful install is not terribly difficult. You can start the install using a command-line installer rather than the GUI:

sudo ./VMware-Remote-Console-11.2.0-16492666.x86_64.bundle --console

There will be some prompting that isn’t present in the GUI. When it asks you:

System service scripts directory (commonly /etc/init.d).:

…enter an alternative directory. That’s it. In my case, it didn’t even have to exist.

The install will take a minute expanding things, and then deposit the “vmrc” executable within the executable search-path. The browser should now be able to find it when the remote console wants to open the viewer.

Go: Build-Time Variables

Go allows you to override global variables at build time during the linker stage:

$ go build -o /tmp/prog-custom -ldflags "-X main.overrideableValuePhrase=123456" ./cmd/prog


  • It must be a global variable and not a constant.
  • It might be in the package that you are telling it to build. This definitely works for executables and, with the removal of support for binary-only packages (BOPs), it probably doesn’t apply whatsoever to intermediate packages.
  • It must be a string (so, process it from the init() function).

It doesn’t matter whether it is an exported or unexported symbol.


Git: Use git-sizer to Identify Large Space Usage in Your History

Notice that it cites the revisions at the bottom:

$ git-sizer -v
Processing blobs: 2049                        
Processing trees: 1056                        
Processing commits: 432                        
Matching commits to trees: 432                        
Processing annotated tags: 0                        
Processing references: 12                        
| Name                         | Value     | Level of concern               |
| ---------------------------- | --------- | ------------------------------ |
| Overall repository size      |           |                                |
| * Commits                    |           |                                |
|   * Count                    |   432     |                                |
|   * Total size               |   143 KiB |                                |
| * Trees                      |           |                                |
|   * Count                    |  1.06 k   |                                |
|   * Total size               |   885 KiB |                                |
|   * Total tree entries       |  21.0 k   |                                |
| * Blobs                      |           |                                |
|   * Count                    |  2.05 k   |                                |
|   * Total size               |  33.8 MiB |                                |
| * Annotated tags             |           |                                |
|   * Count                    |     0     |                                |
| * References                 |           |                                |
|   * Count                    |    12     |                                |
|                              |           |                                |
| Biggest objects              |           |                                |
| * Commits                    |           |                                |
|   * Maximum size         [1] |  1.32 KiB |                                |
|   * Maximum parents      [2] |     2     |                                |
| * Trees                      |           |                                |
|   * Maximum entries      [3] |    66     |                                |
| * Blobs                      |           |                                |
|   * Maximum size         [4] |  4.05 MiB |                                |
|                              |           |                                |
| History structure            |           |                                |
| * Maximum history depth      |   413     |                                |
| * Maximum tag depth          |     0     |                                |
|                              |           |                                |
| Biggest checkouts            |           |                                |
| * Number of directories  [5] |    27     |                                |
| * Maximum path depth     [6] |     4     |                                |
| * Maximum path length    [7] |   105 B   | *                              |
| * Number of files        [6] |   137     |                                |
| * Total size of files    [8] |  4.64 MiB |                                |
| * Number of symlinks         |     0     |                                |
| * Number of submodules       |     0     |                                |

[1]  a52f2b2c86baa9617ed66bc0b3301d57bf763ed3
[2]  fa562d025143096dc8ae0c2294114cd0b4443945 (refs/stash)
[3]  4ca9fdb84fec68c38d6061441996fd15b9494e9d (d2a75bc4b9743a3decf9e6cd5cb4a8670d57f30d^{tree})
[4]  62918aac7359d32b4b342db8d65a5a2a5172215d (86c3344be1fc590ee3ebe9eb7117e91c4ad21450:command/gozipinfo/gozipinfo)
[5]  2b5b648f5e6488420c22ba9c318fc6bfc4ce2a47 (461bbd7555360a202d1ab16f02c992581791a7d2^{tree})
[6]  853678df5f5fe5ec58b169d0fe3878e376c53e3e (refs/heads/dustin/profiling/temp_path^{tree})
[7]  8b03f6bab9d3369fec1fe322f5d3f159a220d95a (1b385e1714b7904fca85943d0f27c7f772af6d0f^{tree})
[8]  a557ab9aff02167856530cf536163d349e44fdfe (86c3344be1fc590ee3ebe9eb7117e91c4ad21450^{tree})

Go: Write RPC-Connected Plugins

Plugins are Go’s system for developing shared-libraries. However, this is backed by a general system that can also have alternative implementations. In this case, you can write a plugin in Go that runs from one system and load that plugin in Go, on the fly, from a million other systems. Courtesy of Hashicorp.



Python: Command-Line Completion for argparse

argcomplete provides very useful functionality that you will basically get for free with just a couple of steps.


Put some markup below the shebang of your frontend script in the form of a comment:

#!/usr/bin/env python

The BASH-completion script argcomplete will basically identify and scan any script with a Python shebang that is used with BASH-completion. This entails actually running the script. In order to minimize how much time is spent loading scripts that don’t actually use argcomplete, the completion script will ignore anything that does not have this comment directly following the shebang.

Next, add and import for the argcomplete package and run argcomplete.autocomplete(parser) after you have configured your command-line parameters but before your call to parser.parse_args() (where parser is an instance of argparse.ArgumentParser). This function will produce command-line configuration metadata and then terminate.

That is it. Note that it is not practical to assume that everyone who uses your script will have argcomplete installed. They may not be using BASH (BASH is the only well-supported shell at this time), they may not be using a supported OS, and/or any commercial environments that adopt your tools may be server environments that have no use for command-line completion and refuse to support it. Therefore, you should wrap the import with a try-except for ImportError and then only call argcomplete.autocomplete if you were able to import the package.


To install autocomplete, the simplest route is to merely do a “sudo pip install argcomplete” and then call “activate-global-python-argcomplete” (this is a physical script likely installed to /usr/local/bin. This only has to be done once and will install a non-project-specific script that will work for any script that is equipped to use argcomplete. For other configuration and semantics, see the project page.