tag:blogger.com,1999:blog-4620065251949857262024-03-26T05:02:30.045-04:00Sandro TosiA blog about things I do: Debian, Linux, Python, whateverSandro Tosihttp://www.blogger.com/profile/17077191422205823991noreply@blogger.comBlogger109125tag:blogger.com,1999:blog-462006525194985726.post-26823745692062275272023-08-10T14:50:00.000-04:002023-08-10T14:50:17.770-04:00Mastodon hook for dput-ng<p>If you use <a href="https://salsa.debian.org/debian/dput-ng" target="_blank">dput-ng</a>, you may be familiar with the <a href="https://salsa.debian.org/debian/dput-ng/-/tree/master/examples/hooks/twitter" target="_blank">Twitter hook</a> that tweets a message when uploading a package.</p><p>A similar hook is <a href="https://salsa.debian.org/debian/dput-ng/-/merge_requests/28" target="_blank">now available</a> for Mastodon too; if interested, give it a try and comment on the MR</p>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-38982681365117034702021-05-22T20:59:00.004-04:002021-05-22T20:59:58.801-04:00QNAP: control LCD panel and speaker<h2 style="text-align: left;"><span style="font-family: inherit;">LCD Panel</span></h2><p><span style="font-family: inherit;">Most (if not all) QNAP models come with an LCD display, in my model i got a 2 lines by 16 characters each. </span><span style="font-family: inherit;">The tool to control the panel is:</span></p>
<pre>/sbin/lcd_tool</pre>
<p><span style="font-family: inherit;">but sometimes it's a bit stubborn in executing the commands, so as mentioned <a href="https://forum.qnap.com/viewtopic.php?t=123575#p554012">here</a> you may want to </span><span style="font-family: courier;">killall -9 lcdmond</span> and <i>then</i> issue the command you want; this is the snippet i'm using:</p>
<pre># print a msg on the panel
killall -9 lcdmond
/sbin/lcd_tool -1 "$LINE1" -2 "$LINE2"
sleep 5
# turn off screen light
killall -9 lcdmond
/sbin/lcd_tool -f
</pre>
<p>it ain't pretty, but it gets the job done.</p><h2 style="text-align: left;"><span style="font-family: inherit;">Speaker / Buzzer</span></h2><p><span style="font-family: inherit;">If you look for how to make your system beep, you may <a href="https://forum.qnap.com/viewtopic.php?t=35847#p156373" target="_blank">find</a> these commands:</span></p>
<pre>/sbin/pic_raw 80 Beep short
/sbin/pic_raw 81 Beep long
</pre>
<p><span style="font-family: inherit;">but they no longer work. So keep looking, i stumbled upon <a href="https://forum.qnap.com/viewtopic.php?t=121543" target="_blank">this post</a>, mentioning </span><span style="font-family: courier;">hal_app</span><span style="font-family: inherit;">, and that indeed works, but with a different syntax than the one presented at that link.</span></p><p><span style="font-family: inherit;">In order to use </span><span style="font-family: courier;">hal_app</span><span style="font-family: inherit;"> to make a beep sound, the syntax that worked for me is:</span></p>
<pre>/sbin/hal_app --se_buzzer enc_id=0,mode=XXX</pre>
If you remove entirely mode=XXX, it produces a short beep, but here is the list of all the modes available and their results (found out via exhaustive search):<div>
<br />
<table style="border: 1px solid black;">
<thead style="border: 1px solid black;">
<tr style="border: 1px solid black;">
<th style="border: 1px solid black;">code</th>
<th style="border: 1px solid black;">output</th>
</tr>
</thead>
<tbody>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">0</td>
<td style="border: 1px solid black;">short beep (0.5 secs)</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">1</td>
<td style="border: 1px solid black;">long beep (1 sec)</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">2</td>
<td style="border: 1px solid black;">3x short beeps (0.5 secs), long pause (1 sec)</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">3-7, 10,<br />15, 16, 17,<br />18, 19, 20</td>
<td style="border: 1px solid black;">2x long beeps (1 sec), very long pause (2 secs)</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">8, 9</td>
<td style="border: 1px solid black;">3x long beeps (1 sec), very long pauses (2 secs)</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">12, 13</td>
<td style="border: 1px solid black;">long beep, 2x very short pause (0.25) very short beep (0.25)</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">14</td>
<td style="border: 1px solid black;">3x very short beep (0.25) very short pause (0.25)</td>
</tr>
</tbody>
</table>
<p><span style="font-family: inherit;">(you can prepend as many 0 to the mode strings as you wish, so 000 is equivalent to 0, 000018 is equivalent to 18, and so on).</span></p><p><span style="font-family: inherit;">PS: this article is based on my system, TVS-473 running firmware 4.5.3.1652</span></p><p><span style="font-family: inherit;">PPS: </span>friendly<span style="font-family: inherit;"> </span>reminder<span style="font-family: inherit;"> that </span><a href="https://wiki.qnap.com/wiki/Add_items_to_crontab" style="font-family: inherit;" target="_blank">this is how you edit the crontab</a><span style="font-family: inherit;"> on a QNAP machine.</span></p></div>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-21700556305449106192021-05-10T17:07:00.003-04:002021-05-10T17:07:40.462-04:00Empire State Building Lights iCalendar<p>I'm very lucky to be able to see the Empire State Building from my apartment windows, and at night the lights are fantastic! But i'm also curious to know what's going to be today's lights, and tomorrow, etc.</p><p>I thought I'd easily find a calendar to add to gCal to show that, but i wasn't able to find any, so I made it myself: <a href="https://sandrotosi.github.io/esb-lights-calendar/">https://sandrotosi.github.io/esb-lights-calendar/</a></p>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-60764513429583355262020-12-25T15:46:00.001-05:002020-12-25T15:46:19.155-05:00Devils: Massimo Ruggiero's apartment building<p>If you enjoyed watching <a href="https://en.wikipedia.org/wiki/Devils_(TV_series)" target="_blank">Devils</a>, like me, and if you tend to obsess over tiny details that have absolutely nothing to do with the story being told, like me, and you lived in that <i>general</i> area, like me, then you may be curious of the location of Massimo's apartment.</p><p>In several shots we can see views of both <a href="http://www.30stmaryaxe.com/" target="_blank">The Gherkin</a> and the north side of <a href="https://canarywharf.com/" target="_blank">Canary Wharf</a>, so that means the building is in and around E1/E2/E3 zip codes. But London is <b>huge</b>, and while yes i tried to just browse Google Maps for clues, that didn't produce any result.</p><p>The final clue is revealed in the 9th episode, at minute 20:10, and precisely with this shot:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-dglTxEOFwDs/X-ZNJFpP-lI/AAAAAAABDUM/3KLdLr5GLfgp3YWPUY3q_5NX5ZryMa3QACLcBGAsYHQ/s1920/shot0008.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1080" data-original-width="1920" height="360" src="https://1.bp.blogspot.com/-dglTxEOFwDs/X-ZNJFpP-lI/AAAAAAABDUM/3KLdLr5GLfgp3YWPUY3q_5NX5ZryMa3QACLcBGAsYHQ/w640-h360/shot0008.png" width="640" /></a></div><p>at the bottom left we can see the entrance sign for <a href="https://www.tobaccodocklondon.com/" target="_blank">Tobacco Dock</a>, located at:</p><p><iframe allowfullscreen="" aria-hidden="false" frameborder="0" height="450" src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2483.274760356203!2d-0.06175638402255718!3d51.50817501846725!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x48760331dd10ff3f%3A0x438a8f1c8d683e45!2sTobacco%20Dock!5e0!3m2!1sen!2sus!4v1608928768124!5m2!1sen!2sus" style="border: 0;" tabindex="0" width="600"></iframe></p><p>So right there, just off to the right from the entrance, it's the apartment building: <a href="https://www.skyscrapercenter.com/building/park-vista-tower/17144" target="_blank">Park Vista Tower</a>.</p><p>The exact apartment number, i don't know, it's probably somewhere on the door or on the door frame, which can probably be seen one of the times when Sofia or others come to visit Massimo, but since that happened mid 9th episode, i'm not gonna go back to find that clue 😀</p>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-1235319211122608682020-12-19T03:16:00.004-05:002020-12-26T17:03:29.814-05:00Gmail and tracker.debian.org: add a label to team emails<p>Recently the <a href="https://wiki.debian.org/Teams/PythonTeam" target="_blank">Python Team</a> started the migration from Alioth mailing list to a <a href="https://tracker.debian.org/" target="_blank">tracker.debian.org</a> <a href="https://tracker.debian.org/teams/python/" target="_blank">team</a>.</p><p>Alioth mailing list, being a real ml, included a <span style="font-family: courier;">List-Id</span> header, which is handled by Gmail natively and which you can use to create a filter based on it.</p><p>Tracker.d.o instead uses a custom header, <span style="font-family: courier;">X-Distro-Tracker-Team</span>, and Gmail doesn't allow to create filters on custom headers. But there's a solution: <a href="https://developers.google.com/apps-script/overview" target="_blank">Google Apps Scripts</a>.</p><h3 style="text-align: left;">1. Apps script and its configuration</h3><p style="text-align: left;">To create a new apps script, click "New project" from the <a href="https://script.google.com/home" target="_blank">scripts dashboard</a>: this will open a code editor, so now cut and paste this code (change the label name to match the one you want to use, and the header too if you're going to use this for another team):</p><pre><code class="javascript">function tagPythonTeamEmails() {
// search for all recent threads (hours is the smallest interval searchable)
var threads = GmailApp.search("newer_than:1h");
// this is the label i want to apply to the messages
var label = GmailApp.getUserLabelByName("Debian_Python_Pkgs"); // <-- EDIT THIS
for (var i = 0; i < threads.length; i++) {
// get all messages in a given thread
var messages = threads[i].getMessages();
// for each message in the thread
for (var j = 0; j < messages.length; j++) {
var message = messages[j];
// needed to have access to the full email: headers + body
var email = message.getRawContent();
// this is the header i want to check for: if present, add label and archive
if (email.indexOf("X-Distro-Tracker-Team: python") > -1) { // <-- EDIT THIS
threads[i].addLabel(label);
threads[i].moveToArchive();
}
}
}
}
</code>
</pre>
<p></p><p style="text-align: left;">(This code is largely inspired by <a href="https://webapps.stackexchange.com/a/73544" target="_blank">this StackOverflow answer</a>.)</p><p style="text-align: left;">Given we're going to perform changes to the emails, we need to add extra permissions to the script; first we need to toggle the option "View > Show manifest file" which will show the <span style="font-family: courier;">appsscript.json</span> file. Once done, edit it and update the <a href="https://developers.google.com/apps-script/concepts/scopes#setting_explicit_scopes" target="_blank">scope</a> of the script to include:</p>
<pre><code class="json"> "oauthScopes": [
...
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/gmail.modify"
],
</code></pre>
<p style="text-align: left;">These new permission will be granted when we deploy the script, which we can actually do right now: from the editor window click on "Publish > Deploy from manifest..." and then "Install add-on"; it will make the app script available to operate on Gmail by opening the usual Google grants authorization popup.</p>
<h3 style="text-align: left;">2. Schedule the app script execution</h3><p style="text-align: left;">Unlike filters defined on the web UI, apps scripts are not triggered every time a mail is received (there's a pub-sub mechanism, but it doesn't look like it would work for this), so if we want to execute periodically the new script, we need to create a <i>time-driven</i> trigger.</p><p style="text-align: left;">The simplest way is probably from the script editor (but you can also follow <a href="https://developers.google.com/apps-script/guides/triggers/installable#managing_triggers_manually" target="_blank">this doc</a>): "View > Current project's triggers" and then "Add trigger" from there. For my specific use-case i set:</p><p style="text-align: left;"></p><ul style="text-align: left;"><li>event source = time-driven</li><li>type of time based trigger = minutes timer</li><li>minute interval = 5 minutes</li><li>Failure notification settings = notify me immediately</li></ul><div>it's not great that you have to wait 5 minutes for getting proper labels, and while it's true you can schedule the trigger for every minute, there are further considerations for that, discussed below.</div><p></p><h3 style="text-align: left;">3. Additional information</h3><p style="text-align: left;">Be aware of <a href="https://developers.google.com/apps-script/guides/services/quotas">quotas and limitations</a> for Apps scripts; in particular the "Triggers total runtime" set to "90 min / day" is what led me to set the trigger every <strike>5</strike>10 mins.</p><p style="text-align: left;">Use the <a href="https://script.google.com/" target="_blank">scripts dashboard</a> (<a href="https://developers.google.com/apps-script/guides/dashboard" target="_blank">doc</a>) to monitor the script execution logs, in the "My Executions" section, and specifically the "Duration" column: the script execution time depends exclusively on the number of emails to process at every execution, so fine-tune the trigger time to stay within your quota.</p><p style="text-align: left;">The <span style="font-family: courier;">newer_than</span> search operator doesn't allow a granularity smaller than hours (although that's not even <a href="https://support.google.com/mail/answer/7190?hl=en" target="_blank">documented</a>), so that means we're going to scan multiple times the same emails.</p><p style="text-align: left;"><b>UPDATE</b> (2020-12-26): I've already had to bump from every 5 to every 10 minutes, as otherwise i'd get <span style="font-family: courier;">Exception: Service invoked too many times for one day: gmail.</span> (remember the quota!)</p>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-56949115053021635932020-12-08T02:13:00.009-05:002021-11-04T09:45:13.848-04:00Python: send emails with embedded images<p>to send emails with images you need to use <span style="font-family: courier;">MIMEMultipart</span>, but the basic approach:</p>
<pre><code class="python">import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
msg = MIMEMultipart('alternative')
msg['Subject'] = "subject"
msg['From'] = from_addr
msg['To'] = to_addr
part = MIMEImage(open('/path/to/image', 'rb').read())
s = smtplib.SMTP('localhost')
s.sendmail(from_addr, to_addr, msg.as_string())
s.quit()
</code>
</pre>
<p>will produce an email with empty body and the image as an attachment.</p><p>The better way, ie to have the image as part of the body of the email, requires to write an HTML body that <i>refers</i> to that image:</p>
<pre><code class="python">import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
msg = MIMEMultipart('alternative')
msg['Subject'] = "subject
msg['From'] = from_addr
msg['To'] = to_addr
text = MIMEText('<img src="cid:image1">', 'html')
msg.attach(text)
image = MIMEImage(open('/path/to/image', 'rb').read())
# Define the image's ID as referenced in the HTML body above
image.add_header('Content-ID', '<image1>')
msg.attach(image)
s = smtplib.SMTP('localhost')
s.sendmail(from_addr, to_addr, msg.as_string())
s.quit()
</code>
</pre>
The trick is to define an image with a specific Content-ID and make that the only item in an HTML body: now you have an email with contains that specific image as the only content of the body, embedded in it.<div><br /></div><div><b>Bonus point</b>: if you want to take a snapshot of a webpage (which is kinda the reason i needed the code above) i found it extremely useful to use the <a href="https://developers.google.com/speed/docs/insights/v5/get-started" target="_blank">Google PageSpeed Insights API</a>; a good description on how to use that API with Python is available at <a href="https://stackoverflow.com/a/63929634/1929629">this</a> StackOverflow answer.</div><div><br /></div><div><b>UPDATE</b> (2020-12-26): I was made aware via email that some mail providers may not display images inline when the <span style="font-family: courier;">Content-ID</span> value is too short (say, for example, <span style="font-family: courier;">Content-ID: 1</span>). A solution that seems to work on most of the providers is using a sequence of random chars prefixed with a dot and suffixed with a valid mail domain.</div>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-77509841957277488172020-11-05T21:42:00.005-05:002020-12-26T14:47:21.796-05:00QNAP firmware 4.5.1.1465: disable ssh management menu<p>as a good boy i just upgraded my QNAP NAS to the latest available firmware, 4.5.1.1465, but after the reboot there's an ugly surprise awaiting for me</p><p>once i ssh'd into the box to do <i>my stuff</i>, instead of a familiar bash prompt i'm greeted by a management menu that allows me to perform some basic management tasks or quit it and go back to the shell. i dont really need this menu (in particular because i have automations that regularly ssh into the box and they are not meant to be interactive).</p><p>to disable it: edit <span style="background-color: white; font-family: monospace;">/etc/profile </span>and comment the line "<span style="background-color: white; font-family: monospace;">[[ "admin" = "$USER" ]] && /sbin/qts-console-mgmt -f</span>" (you can judge me later for sshing as root)</p><p><b>UPDATE</b> (2020-12-26): as pointed out in the comments, and discovered now after an upgrade, the menu comes back up after because <span style="font-family: courier;">/etc/profile</span> is a system file for QNAP so gets replaced/updated by them often</p>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com13tag:blogger.com,1999:blog-462006525194985726.post-35615315329887279692020-10-23T22:32:00.004-04:002020-10-24T14:22:32.871-04:00Multiple git configurations depending on the repository path<p>For my work on Debian, i want to use my debian.org email address, while for my personal projects i want to use my gmail.com address.</p><p>One way to change the <span style="font-family: monospace;">user.email</span> git config value is to <span style="font-family: monospace;">git config --local</span> in every repo, but that's tedious, error-prone and doesn't scale very well with many repositories (and the chances to forget to set the right one on a new repo are ~100%).</p><p>The solution is to use the <span style="font-family: monospace;">git-config</span> ability to include extra configuration files, based on the repo path, by using <span style="font-family: monospace;"><a href="https://git-scm.com/docs/git-config#_includes">includeIf</a></span>:</p>
<p>Content of <span style="font-family: monospace;">~/.gitconfig</span>:</p><p><span style="font-family: monospace;">
</span></p><pre><span style="font-family: monospace;">[user]
name = Sandro Tosi
email = <personal.address>@gmail.com
[includeIf "gitdir:~/deb/"]
path = ~/.gitconfig-deb
</span></pre>
<p>Every time the git path is in <span style="font-family: monospace;">~/deb/</span> (which is where i have all Debian repos) the file <span style="font-family: monospace;">~/.gitconfig-deb</span> will be included; its content:</p>
<pre>[user]
email = morph@debian.org
</pre><p></p>
That results in my personal address being used on all repos not part of Debian, where i use my Debian email address. This approach can be extended to every other git configuration values.Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com2tag:blogger.com,1999:blog-462006525194985726.post-92176811226945673762020-06-11T02:13:00.001-04:002020-06-11T02:13:25.725-04:00Installing prometheus snmp_exporter on a QNAP nasI've this project in the background about creating a grafana <a href="https://github.com/sandrotosi/qnap-dashboards">dashboard</a> for a QNAP nas.<div><br /></div><div>As the summer is ramping up, i wanted to figure out the temperature of the nas throughout the day, so.. prometheus + grafana to the rescue!</div><div><br /></div><div>I wrote the <a href="https://github.com/sandrotosi/qnap-dashboards#install-and-configure-the-snmp-exporter">instructions to install <font face="courier">snmp_exporter</font></a> on a linux-based QNAP nas. For now i'm using an already existing <a href="https://grafana.com/grafana/dashboards/9330">dashboard</a>, but it's the first step to create my own.</div>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-69803735193664714792020-05-08T22:37:00.001-04:002020-05-08T23:08:26.463-04:00It's a waiting game... but just how long we gotta wait?While waiting for my priority date to become current, and with enough "quarantine time" on my hand, i just come up with a very simple Python tool to parse the <a href="https://travel.state.gov/content/travel/en/legal/visa-law0/visa-bulletin.html" target="_blank">USCIS Visa Bulletin</a> to gather some data from that.<br />
<br />
You can find code and images in this <a href="https://github.com/sandrotosi/uscis-visa-bulletin" target="_blank">GitHub repo</a>.<br />
<br />
For now it only contains a single plot for the EB3 final action date; it answers a simple question: how many months ago your priority date should be if you want to file your AOS on that month. We started from FY2016, to cover the final full year of the Obama administration.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-6NSndbpdClI/XrYWsc_mnlI/AAAAAAAA-as/89DQpYQTOQUvPmznHEWoXS8O9iCvZ0XBwCLcBGAsYHQ/s1600/EB3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="960" data-original-width="1536" height="400" src="https://1.bp.blogspot.com/-6NSndbpdClI/XrYWsc_mnlI/AAAAAAAA-as/89DQpYQTOQUvPmznHEWoXS8O9iCvZ0XBwCLcBGAsYHQ/s640/EB3.png" width="640" /></a></div>
If you're interested in more classes/visas, let me know and the tool could be easily extended to cover that too. PRs are always welcome.Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-50398577404711512342016-12-11T12:25:00.004-05:002016-12-11T12:25:53.950-05:00What's that code: Elementary S04E09they hacked a car and around 7:27 in the episode they are analyzing the car's computer source code, <i>that's some sweet compression</i> they say, but it turns out it's Perl interpreter source code, with Perl replaced with Auto (after all it's the auto code right?)<br />
<br />
https://perl5.git.perl.org/perl.git/blob/HEAD:/perl.c#l431 and following lines<br />
<br />
another interesting code copy was in The Americans (cant remember season or episode), when they were trying to acquire the ECHO program source code, what's on the screen is actually MATLAB source codeSandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-59486177549576668972016-11-02T14:01:00.001-04:002016-11-02T14:01:16.961-04:00Debian source package name from the binary nameit looks like i forgot all the times how to do that, and apparently i'm not able to use google good enough to find it out quickly, let's write down one way to get the source package name from the binary package name:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">dpkg-query -W -f='${source:package}\n' <list of bin pkgs></span><br />
<br />
(since it accepts a list of packages, you can xargs it).<br />
<br />
there are probably another million ways to do that, so dont be shy and comment this post if you want to share your methodSandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com1tag:blogger.com,1999:blog-462006525194985726.post-43938732693244632492015-07-25T09:05:00.000-04:002015-07-25T09:06:57.907-04:00How to change your Google services locationSeveral services in Google depends on your location, in particular on <a href="https://play.google.com/store" target="_blank">Google Play</a> (things like apps, devices, contents can be restricted to some countries), but what to do if you relocate and want to update your information to access those <i>exclusive</i> services? Lots of stories out there to make a payment on the playstore with updated credit card info etc etc, it's actually a bit different, but not that much.<br />
<br />
There are 3 places where you need to update your location information, all of them on <a href="https://payments.google.com/" target="_blank">Google Payments</a>:<br />
<br />
<ol>
<li>in <a href="https://payments.google.com/manage/#paymentMethods:" target="_blank">Payment Methods</a>, change the billing address of all your payment methods;</li>
<li>in <a href="https://payments.google.com/manage/#addressBook:" target="_blank">Address Book</a>, change the default shipping address;</li>
<li>in <a href="https://payments.google.com/manage/#settings:" target="_blank">Settings</a>, change your home address.</li>
</ol>
<div>
Once that's done, wait some minutes, and you might also want to logout/login again in your Google account (even tho Google support will tell it's not necessary, it didnt work for me otherwise) and you should be ready to go.</div>
Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-43544705286943155992015-07-25T08:51:00.003-04:002015-07-25T08:53:13.724-04:00DICOM viewer and converter in Debian<a href="https://en.wikipedia.org/wiki/DICOM" target="_blank">DICOM</a> is a standard for your RX/CT/MRI scans and the format most of the times your result will be given to you, along with Win/MacOS viewers, but what about Debian? the best I could find is <a href="http://ginkgo-cadx.com/en/" target="_blank">Ginkgo CADx</a> (package <span style="font-family: Courier New, Courier, monospace;">ginkgocadx</span>).<br />
<br />
If you want to convert those DICOM files into images you can use <span style="font-family: Courier New, Courier, monospace;">convert</span> (I dont know why I was surprised to find out imagemagik can handle it).<br />
<br />
PS: <a href="http://www.cabiatl.com/mricro/dicom/" target="_blank">here</a> a description of the format.Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com1tag:blogger.com,1999:blog-462006525194985726.post-7249606005645986052015-06-23T15:37:00.000-04:002015-06-23T15:37:45.522-04:00CFEngine: upgrade Debian packagessay you use CFEngine to install Debian packages on your server, so it's likely you'll have a bundle looking like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">bundle agent agentname</span><br />
<span style="font-family: Courier New, Courier, monospace;">{</span><br />
<span style="font-family: Courier New, Courier, monospace;"> vars:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> "packages" slist => {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> "pkg1",</span><br />
<span style="font-family: Courier New, Courier, monospace;"> "pkg2",</span><br />
<span style="font-family: Courier New, Courier, monospace;"> "pkg3"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> };</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> packages:</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span>
<span style="font-family: 'Courier New', Courier, monospace;"> "$(packages)"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> package_policy => "addupdate",</span><br />
<span style="font-family: Courier New, Courier, monospace;"> package_method => apt_get;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<br />
this works great to guarantee those packages are installed, but if a newer version is available in the repositories, that wont be installed. If you want CFEngine to do that too, then the web suggests this trick:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> packages:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> "$(packages)"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> package_policy => "addupdate",</span><br />
<span style="font-family: Courier New, Courier, monospace;"> package_version => "999999999",</span><br />
<span style="font-family: Courier New, Courier, monospace;"> package_method => apt_get;</span><br />
<br />
which tweak the install system declaring that you want to install version 999999999 of each package, so if you have available a higher version than the one installed, CFEngine will happily upgrade it for you. It works great.. but sometimes it doesn't. why oh why?<br />
<br />
That's because Debian versions can have a <a href="https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version">epoch</a>: every <i>plain</i> version (like 1.0-1) has an implicit epoch of 0, and same goes for the 999999999 above, that means if any of the installed packages has an epoch, that version will sort higher than 999999999 and the package wont be upgraded. If you want to be sure to upgrade every package, then the right solution is:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> packages:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> "$(packages)"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> package_policy => "addupdate",</span><br />
<span style="font-family: Courier New, Courier, monospace;"> package_version => "9:999999999",</span><br />
<span style="font-family: Courier New, Courier, monospace;"> package_method => apt_get;</span>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com4tag:blogger.com,1999:blog-462006525194985726.post-6619809372045033592012-11-21T12:29:00.000-05:002012-11-21T13:44:59.737-05:00Attending the CodecademyYou've probably already got it, I'm surveying several sites to improve programming skills. This episode is about <a href="http://www.codecademy.com/">Codecademy</a>.<br />
<br />
It's a very well done site, for people that want to <i>learn</i> a language. It has a <a href="http://www.codecademy.com/tracks/python">Python track</a>, along with several others: Ruby, JQuery, Javascript & so on.<br />
<br />
You'll be required to actually write code and <i>run</i> it! yes, the code you write is then executed in a web "interpreter" (modified for educational purposes) and the output displayed on screen. In a section is also possible to write to files and have their contents shown on another tab.<br />
<br />
I'd encourage you to start from it if you never saw Python and you're willing to learn if from the ground up.Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com3tag:blogger.com,1999:blog-462006525194985726.post-38060381874594511932012-11-18T13:22:00.003-05:002012-11-18T13:22:37.493-05:00Spending a Sunday on CodingBat.comI've played a bit with <a href="http://projecteuler.net/">Project Euler</a> but all of their problems are math-centric, which is nice but not exactly what I'm looking for: some real-world programming problems to <i>get back into the coding field</i>.<br />
<br />
So asking my friend Google, I found <a href="http://codingbat.com/">CodingBat</a>: it has a Python <a href="http://codingbat.com/python">section</a> with several tasks to complete. I must say they are some kinda trivial to solve, once you know some idiomatic Python code, but some are a bit more interesting. If you're a junior Python coder, or want to get a grip on the language, give it a look.<br />
<br />
Oh, and if you know some website that would give me some real-world programming coding problems (something that would be useful on the job, not just coding for fun), I would love to hear you.Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com6tag:blogger.com,1999:blog-462006525194985726.post-8557068211789754552012-11-14T14:40:00.000-05:002012-11-14T14:40:11.066-05:00Project Euler - Problem 6<br />
Here's my solution to <a href="http://projecteuler.net/">Project Euler</a> <a href="http://projecteuler.net/problem=6">problem 6</a>:<br />
<br />
<pre class="prettyprint"># where the numbers list ends
n = 100
# handy function to square a number
pow2 = lambda x: pow(x, 2)
# first compute the sum of the squares
sumsq = sum(map(pow2, range(1, n+1)))
# then the square of the sum
sqsum = pow2(sum(range(1, n+1)))
print sqsum - sumsq
</pre>
Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com4tag:blogger.com,1999:blog-462006525194985726.post-66818632379466412222012-11-14T14:03:00.001-05:002012-11-14T15:31:55.169-05:00Project Euler - Problem 4Here's my solution to <a href="http://projecteuler.net/">Project Euler</a> <a href="http://projecteuler.net/problem=4">problem 4</a>:<br />
<br />
<pre class="prettyprint"># handy function to check if a number is palindrome
def is_palindrome(i):
return str(i) == str(i)[::-1]
# what's the max?
max_p = 0
# multiply all numbers `i` between 100 and 998, with all between i+1 and 999
for i in xrange(100, 999):
for j in xrange(i+1, 1000):
p = i * j
if is_palindrome(p) and p > max_p:
max_p = p
print max_p
</pre>
<br />
Comments are welcome.<br />
<br />
<b>Update</b>: fixed as per Alex comment.Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com13tag:blogger.com,1999:blog-462006525194985726.post-89248494142023429312012-10-28T16:26:00.004-04:002012-10-28T16:26:51.977-04:00Start a MySQL instance to run Debian package build-time testsI'm the maintainer of <a href="http://dev.mysql.com/doc/connector-python/en/index.html">MySQL Connector/Python</a> <a href="http://packages.qa.debian.org/m/mysql-connector-python.html">Debian package</a>, and it's shipped with several unittests, but they require a MySQL instance to be run against, so up to know I wasn't able to run them at build-time.<br />
<br />
But I want to change that, so I wanted to find a way to spawn a MySQL instance just for testing purposes. I've searched a lot, and then found a package solving the same problem: <a href="http://packages.qa.debian.org/p/php5.html">php5</a>.<br />
<br />
The package has a <a href="http://anonscm.debian.org/gitweb/?p=pkg-php/php.git;a=blob;f=debian/setup-mysql.sh">setup-mysql.sh</a> script that takes care of starting/stopping the instances, and <a href="http://anonscm.debian.org/gitweb/?p=pkg-php/php.git;a=blob;f=debian/rules">debian/rules</a> file sets up <a href="http://anonscm.debian.org/gitweb/?p=pkg-php/php.git;a=blob;f=debian/rules#l46">instance parameters</a> and then it <a href="http://anonscm.debian.org/gitweb/?p=pkg-php/php.git;a=blob;f=debian/rules#l182">starts</a> the instance before the tests and then <a href="http://anonscm.debian.org/gitweb/?p=pkg-php/php.git;a=blob;f=debian/rules#l209">stops</a> it after them.<br />
<br />
It's a very interesting solution, so I thought of sharing + taking notes to self, just in case I need it in other situations.Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com2tag:blogger.com,1999:blog-462006525194985726.post-80482322247113556612012-06-03T14:03:00.000-04:002012-06-03T14:03:26.484-04:00How to migrate your entire Google account to a new oneI've been using a Google account since years, but having a "more serious" one along. The time has come to make the switch and elect the other as main one.<br />
<br />
Google has a lot of services, and I'm using several of them, so changing the main account requires to migrate data of those services to the new account, given it's <a href="http://support.google.com/accounts/bin/answer.py?hl=en&answer=63304">not possible</a> to merge two accounts. To know the full list of services your account is signed in, go to your <a href="https://www.google.com/settings/products">Account Product page</a>. Some migrations are easy, others hell no: so I'm writing this post to keep track of the migration as it's going on.<br />
<br />
First of all, there's a really good post about this migration at <a href="http://lifehacker.com/5602545/how-to-migrate-your-entire-google-account-to-a-new-one">LifeHacker</a>: it contains a lot of info I'm using here, but not all the services I need. Additionally, Google has a <a href="http://support.google.com/accounts/bin/answer.py?hl=en&answer=58582">list</a> of services and methods to migrate from one account to another.<br />
<br />
Just to be generic, I'll call <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span> the original account and <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> the one I want to migrate to.<br />
<br />
<span style="font-size: large;">Migrate GMail</span><br />
<br />
<a href="https://mail.google.com/mail/">GMail</a> is probably the most important service I have, and also the most difficult one to migrate. I have a lot of filters, so the first step is to migrate them:<br />
<ol>
<li>Login into GMail for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Gear icon > Settings > Labs</li>
<li>Enable the "Filter import/export" plugin</li>
<li>Reload GMail to enable the plugin (if not done automatically)</li>
<li>Gear icon > Settings > Filters</li>
<li>At the bottom of the page, Select all</li>
<li>Export: this will download an XML file with the filters in it</li>
<li>Login into GMail for <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<li>Enable "Filter import/export" plugin</li>
<li>Load the file containing the saved filters</li>
<li>Import all (or select which one) filters; this will also create automatically the labels defined in the filters.</li>
</ol>
I currently have a <a href="https://support.google.com/mail/bin/answer.py?hl=en&answer=10957">forward rule</a> from <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> to <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span>: so let's revert the forward direction: from <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span> to <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span>. This will allow the new account to receive the mails sent to the old one.<br />
<ol>
<li>Login into GMail for <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<li>Gear icon > Forwarding and POP/IMAP > Disable forwarding: this will stop redirecting mails from <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> to <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Login into GMail for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Gear icon > Forwarding and POP/IMAP > add a forwarding address</li>
<li>Enter <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> as the address to forward mails to</li>
<li>A verification code is sent to <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> and you'll need to enter that code in <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span> to verify you have access to both mailboxes</li>
<li>Once verified, select "Forward a copy of incoming mail to" to <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> and to delete the GMail copy on <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
</ol>
<div>
<span style="font-family: inherit;">There's no automatic way to migrate all your settings from the old GMail account to the new one, so you'll have to comparing settings pages to set what you had before to </span><span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span><span style="font-family: inherit;">. I suggest to first enable the labs you have on </span><span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span><span style="font-family: inherit;">, and then go thru every page and report the configurations.</span></div>
<div>
<br /></div>
<div>
Did I forget something? yes, the hardest part: migrate mails! There are a lot of <a href="http://lifehacker.com/352401/migrate-all-your-old-gmail-to-a-new-gmail-address">guides</a> about <a href="http://knol.google.com/k/changing-your-gmail-username-or-email-address">migrating</a> mails, the way I prefer is thru IMAP and Thunderbird (as described <a href="http://www.twistermc.com/27915/move-gmail-to-gmail/">here</a>): you'll move IMAP folders, and since they are equivalent to GMail labels, you'll automatically get your email with the correct labels (yes, the same mail appears in several folders, one for each label, and moving an email from one folder will not remove it from all the others).</div>
<div>
<ol>
<li>Enable IMAP access on both <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span> and <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">O</span>pen Thunderbird (or Icedove if you're on Debian like me) and register both accounts</li>
<li>You can now start moving folders/emails from <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span> to <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<ol>
<li>Copying a (missing) folder, will automatically create a label with the same name</li>
<li>Moving a mail from the same folders on the two accounts will add the label called with the name of the folder to that email</li>
</ol>
<li>Be ready, it's a LOOOOONG process, but it's safe and it guarantees a perfect result</li>
</ol>
</div>
<div>
With the method above you have all the labels you had before, but not the label colors (and I have a lot :( ).<br />
<br />
Another tool that's would be interesting to evaluate for this task is <a href="http://gmvault.org/">Gmvault</a>.</div>
<br />
<br />
<span style="font-size: large;">Migrate Contacts</span><br />
<br />
<a href="https://mail.google.com/mail/#contacts">Contacts</a> are available inside GMail:<br />
<ol>
<li>Login into GMail for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>On the combobox on top-left, select Contacts</li>
<li>More > Export</li>
<li>Export all the contacts in Google CSV, since it's specific to be re-imported</li>
<li>Login into GMail for <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<li>Contacts > More > Import</li>
<li>Select the previously saved file and import it</li>
</ol>
<br />
<span style="font-size: large;">Migrate Reader</span><br />
<br />
Migrating <a href="http://www.google.com/reader/">Reader</a> subscriptions is easy:<br />
<ol>
<li>Login into Reader for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Reader Settings -> Import/export</li>
<li>Export your subscriptions in OPML format</li>
<li>Now login into Reader for <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<li>Reader Settings -> Import/export</li>
<li>And import the saved OPML file</li>
</ol>
<div>
Sadly, that doesn't migrate your starred items, but there's a (long & manual) solution <a href="http://realityloop.com/blog/2009/07/04/how-transfer-new-google-reader-account-including-your-starred-items">here</a>.</div>
<br />
<br />
<span style="font-size: large;">Migrate Blogger</span><br />
<br />
Login to <a href="http://www.blogger.com/">Blogger</a> for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span>; then, for each blog you have there do this dance:<br />
<ol>
<li>Select the blog</li>
<li>Go into Settings > Permissions</li>
<li>Add <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> as a new author: this will send an email to <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> GMail account</li>
<li>Accept the invitation (this will ask you to create a new Blogger account for <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> if you don't already have one)</li>
<li>Go back to to Blogger with <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Blog > Settings > Permissions</li>
<li>Grand admin rights to <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
</ol>
<div>
At this point, both <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span> and <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> have admin rights; you can leave it as it is, or remove <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span> and so only <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> will be the admin (other shares should be kept unchanged). The same procedure is described in <a href="http://support.google.com/blogger/bin/answer.py?hl=en&answer=41448">this Google support answer</a>.</div>
<div>
<br /></div>
<div>
What can't be migrated as easily are all the profile settings you've done on <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span>. So profile information, blogs followed and so on have to be migrated by hand: boring but they are just few things, doable in a bunch of minutes.<br />
<br />
<br />
<span style="font-size: large;">Migrate Android phone</span><br />
<br />
<a href="http://www.android.com/">Android</a> phones require a primary Google account to work, and of course my phone uses <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span>. <a href="http://www.technipages.com/android-change-main-google-account.html">Several</a> <a href="http://www.androidegis.com/google/learn-how-to-change-primary-email-account-with-android/">sources</a> say the only way to change primary account is to factory reset the phone. But since <a href="http://www.theandroidsoul.com/multiple-accounts-sign-in-logins-supported-in-the-latest-android-market-v3-0-26/">new market app</a> supports multiple accounts and Android 4.0 (Ice Cream Sandwich) <a href="http://groups.google.com/a/googleproductforums.com/d/msg/gmail/EPRCXY3wCgM/RhlzDfPIk80J">not longer needs</a> a primary account, I just waited for the update to ICS to come.<br />
<br />
What you really need to do is to add a new account, <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span>, to Settings > Account & Sync, and all the Google apps on the phone will be able to use the new account (you might need to select what to sync, and the new account from inside each app).<br />
<br />
<br />
<span style="font-size: large;">Migrate Calendar</span><br />
<br />
Even with <a href="https://www.google.com/calendar/">Calendar</a> the settings will have to be migrated by hand: they are just in one page, so just keep two windows opened and keep switching to sync them. The calendars are easy to move over: for the main calendar:<br />
<ol>
<li>Login into Calendars for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Go into Settings > Calendars tab</li>
<li>Select export calendars: this will download an archive of your calendars in a zip file; you will need to extract all the ics files from that zip archive so you'll have the main calendar readily available</li>
<li>Login into Calendars for <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<li>Settings > Calendars tab</li>
<li>Import the main calendar</li>
</ol>
<div>
for the other calendars you can do this way:</div>
<div>
<ol>
<li>Login into Calendars for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Settings > Calendars tab</li>
<li>Share the calendar with <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> and give it "Make changes AND manage sharing" right - the new account will have full control over that calendar</li>
</ol>
<div>
<br /></div>
<div>
<span style="font-size: large;">Migrate Docs</span></div>
</div>
<div>
<br /></div>
<div>
The procedure to migrate documents in Google <a href="https://docs.google.com/">Docs</a> (now Google <a href="https://drive.google.com/">Drive</a>) is described <a href="http://support.google.com/docs/bin/answer.py?hl=en&answer=92358">here</a>, and it boils down to:</div>
<div>
<ol>
<li>Login into Docs for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Select all the documents</li>
<li>Share them with <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<li>In the same window select <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> as "is owner"</li>
</ol>
<div>
and you've got all the docs as owned by the new account.<br />
<br /></div>
</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Migrate Groups</span></div>
<div>
<br /></div>
<div>
There's no way to migrate all your <a href="https://groups.google.com/">Groups</a> subscriptions from one account to another (if not playing with alternate email address, but it was too risky to try it), so you'll have to migrate all of them by hand.</div>
<div>
<br /></div>
<div>
On the other hand, if you've created some groups, that's possible to move them to the new account:</div>
<div>
<ol>
<li>Login into Groups for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Enter in the "manage" area for the groups you've created</li>
<li>Manage members > Invite members</li>
<li>Invite <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<li>Accept the invitation, clicking on the email sent to <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> account</li>
<li>Go back into <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span> manage area</li>
<li>Select the <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> account</li>
<li>Edit the subscription and set "Membership type" to "owner": now <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> is the owner of the list</li>
</ol>
<div>
<br /></div>
<div>
<span style="font-size: large;">Migrate Analytics</span><br />
<br />
The process to migrate the account on Google <a href="http://www.google.com/analytics/">Analytics</a> is <a href="http://groups.google.com/a/googleproductforums.com/d/msg/analytics/lz_gVxtupkM/ym9FhS_9ZAgJ">similar</a> to Groups:<br />
<ol>
<li>Login into Analytics for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Select Admin on top-right, then for each account you have</li>
<li>Select the account, select "Users" tab, click on "+ New User"</li>
<li>Enter <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> into the "Email Address" field and give that account the "Administrator" role</li>
<li>Save</li>
<li>Now <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> is able to access the same data on Analytics as <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
</ol>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
</div>
</div>
<div>
<span style="font-size: large;">Migrate Picasa</span></div>
<div>
<br /></div>
<div>
To transfer your whole <a href="https://picasaweb.google.com/">Picasa</a> account follow these steps (as also described in this <a href="http://support.google.com/picasa/bin/answer.py?hl=en&answer=189356">support post</a>):<br />
<ol>
<li>Login into Picasa for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Click on the gear on top-right > Photo Settings > Privacy and permissions</li>
<li>On the "Migrate account" line click on "Migrate my photos"</li>
<li>Insert <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> into the box for destination address</li>
<li>In case you're using picasa to store blogger photos, also select the tick below</li>
<li>At this point, <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span> will receive an email: copy the link in a session where you've logged in as <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> and then visit the page: that will start the process</li>
<li>Wait until the transfer is completed: you'll receive an email to <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> when it's done</li>
</ol>
<div>
<br /></div>
<div>
<span style="font-size: large;">Migrate Google+</span></div>
<div>
<br /></div>
<div>
I'm not exactly a heavy user of <a href="https://plus.google.com/">G+</a> but I have some circles I'd like to move over (also because Reader sharing now works with G+ and it's a feature I user a lot), <a href="http://support.google.com/plus/bin/answer.py?hl=en&answer=1716102">this</a> is a process to move circles and contacts; as stated there, there's no way to move shared items and stuff (sad!).<br />
<br /></div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Migrate AdSense</span></div>
<div>
<br /></div>
<div>
It's not possible to migrate the current <a href="https://www.google.com/adsense/">AdSense</a> account: you have to register a new one. When you do, it's possible that Google notice the new account is for the same person of the first one, and will ask to close the old account on AdSense in favor of the new one.<br />
<br /></div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Migrate Alert</span></div>
<div>
<br /></div>
<div>
<a href="http://www.google.com/alerts/">Alerts</a> allows to export the list of alerts you've created but it's not possible to import that list in another Google account, so you'll have to recreate them from scratch (I had just a few so it was a matter of 1 minute or so).<br />
<br /></div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Migrate Zoho Notebook</span><br />
<br />
If you still miss Google Notebook (why big-G you let it die? couldn't you open-sourced it? it was so awesome! anyway...), you probably know that there are two main alternatives to it: <a href="http://evernote.com/">Evernote</a> and <a href="https://notebook.zoho.com/">Zoho Notebook</a>. I decided to go with Zoho (I'm not entirely happy with it, but it's running for now), and given it allows to login with Google account, it was currently using <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span>, so I need to migrate that too:<br />
<ol>
<li><span style="font-family: 'Courier New', Courier, monospace;"><span style="font-family: 'Times New Roman';">Login into <a href="https://notebook.zoho.com/">Zoho Notebook</a> for </span><span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></span></li>
<li>My Account > Profile > Email address</li>
<li>"Add new email" and add <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span>, it will send a confirmation email</li>
<li>Then "Make Primary" on <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span>, so now the new account can login into Zoho notebook with the Google info and have all the notes there.</li>
</ol>
<div>
<br /></div>
<span style="font-size: large;">Migrate Bookmarks</span><br />
<br />
Google provides a <a href="http://support.google.com/bookmarks/bin/answer.py?hl=en&answer=178166">guide</a> to migrate <a href="https://www.google.com/bookmarks/">Bookmarks</a> from one account to another that basically is:<br />
<ol>
<li>Login into Bookmarks for <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span></li>
<li>Click on <a href="https://www.google.com/bookmarks/bookmarks.html?hl=en">Export bookmarks</a> and it will save an HTML file with the bookmarks in it</li>
<li>Import the file in a browser</li>
<li>Use the <a href="http://toolbar.google.com/">Google toolbar</a> to import in into <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
</ol>
<div>
That's kinda ugly way, but it seems to work.</div>
<div>
<br /></div>
<br />
<span style="font-size: large;">Re-enable Web History</span><br />
<br />
If you used <a href="https://www.google.com/history/">History</a>, then you need to re-enable it on the new account:<br />
<ol>
<li>Login into History for <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span></li>
<li>Click on "Turn Web History on" to enable Web History on the new account</li>
</ol>
but it seems to be impossible to export/import or migrate the history from one account to another, that's a shame: years and years of stats lost.<br />
<br />
<br />
<span style="font-size: large;">Migrate Books</span><br />
<br />
<a href="http://books.google.com/">Books</a> doesn't allow to migrate the contents between accounts, so you'll have to do it by hand:<br />
<ol>
<li>Select one book from <span style="font-family: 'Courier New', Courier, monospace;">AccountSRC</span>, copying its link</li>
<li>Go to <span style="font-family: 'Courier New', Courier, monospace;">AccountDST</span> and navigate to the copied link</li>
<li>Add the book to the right category, as it was before.</li>
</ol>
<br />
<span style="font-size: large;">Migrate Webmaster Tools</span><br />
<br />
Google released a <a href="http://support.google.com/webmasters/bin/answer.py?hl=en&answer=44227">document</a> that describes how to migrate to another account; it's similar to Analytics and Groups migration.<br />
<br />
In addition to that, you might also want to <a href="https://support.google.com/webmasters/bin/answer.py?hl=en&answer=2454036">become an owner</a>, that will give full control on the sites.<br />
<br />
<br />
<span style="font-size: large;">Did I forget some services? Let me know!</span><br />
<br />
Everyone has a different experience with Google products, so in case you want me to let know how you migrated from one account to another for a product I didn't mentioned, just leave a comment and I'll edit the post (to be as complete as possible).</div>
<ul>
</ul>
</div>
</div>Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com18tag:blogger.com,1999:blog-462006525194985726.post-41170000348949695332012-04-14T10:42:00.001-04:002012-04-14T13:32:12.598-04:00Mercurial: what's the tag containing this changeset?In software development, you often need to know: when was this feature released? in which releases was this changeset included?<br />
<br />
Typical example is: you're debugging a problem, you find out what's the changeset introducing it, now you want to know when that changeset was firstly released (i.e. included in a tag) - how to do that?<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">hg log -r "<i>cset</i>:: and tag()"</span><br />
<br />
where <span style="font-family: 'Courier New', Courier, monospace;">cset</span> is the changeset you're looking for.<br />
<br />
So know I know that <a href="http://sphinx.pocoo.org/">Sphinx</a> <a href="https://bitbucket.org/birkenfeld/sphinx/issue/322/improve-search-responsiveness">new way to load searchindex.js</a> was introduced in the <a href="https://bitbucket.org/birkenfeld/sphinx/changeset/423faa03c908">this</a> changeset, and released for the first time in 1.0b2:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">$ hg log -r "423faa03c908:: and tag()"</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">changeset: 2261:b494009dccf1</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">tag: 1.0b2</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">user: Georg Brandl <georg@python.org></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">date: Sun May 30 19:52:08 2010 +0200</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">summary: Release preparation for 1.0b2.</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">...</span><br />
<br />
awesome!<br />
<br />
PS: why did I need to know that? because <a href="http://matplotlib.sourceforge.net/">Matplotlib</a> is <a href="https://github.com/matplotlib/matplotlib/issues/820">still using</a> the old way, but Debian <a href="http://anonscm.debian.org/viewvc/python-modules/packages/matplotlib/trunk/debian/patches/60_new_syntax_to_load_searchindex.patch?revision=21105&view=markup">needs</a> the new one.Sandro Tosihttp://www.blogger.com/profile/13017373086527472437noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-31324746129039078862011-12-01T10:58:00.000-05:002011-12-01T10:58:00.407-05:00Get the lines unique on the first field(s)<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">uniq</span> is a great tool, since it returns the unique (adjacent) lines of the given input. But it has a limitation: it can't check for uniqueness only the first N fields (while it allows to <i>ignore</i> them, weird).<br />
<br />
So, what to do if you have a long file, and lines with several fields, but you're only interested in getting the line with the different first 2 field (but all the rest of the line content? <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">awk</span> to the rescue!<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$ awk '!x[$1]++' file</span><br />
<br />
will print the (complete) lines of <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">file</span> that has the first field unique. You can set <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$1$2</span> to have lines unique on the first 2 fields, and so on. Thanks to this forum <a href="http://www.unix.com/unix-dummies-questions-answers/49649-uniq-using-only-first-field.html#post302158457">post</a>, but there's <a href="http://stackoverflow.com/questions/5123820/removing-lines-containing-a-unique-first-field-with-awk">some</a> <a href="http://stackoverflow.com/questions/7602174/how-to-only-print-lines-with-unique-fields">other</a> interesting articles.Sandro Tosihttp://www.blogger.com/profile/17077191422205823991noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-36641564188175752752011-11-03T04:33:00.003-04:002011-11-03T04:34:31.798-04:00Trick of today: find -daystartWhat to get the files older than today? Run<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">find /path/ -type f -daystart -mtime +0</span><br />
<br />
it will return only the files older than today, no matter the time the command is executed (by default, <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">-mtime</span> counts multiples of 24 hours from now). Kinda nice when you want to archive yesterday log files.Sandro Tosihttp://www.blogger.com/profile/17077191422205823991noreply@blogger.com0tag:blogger.com,1999:blog-462006525194985726.post-39730020626438255482011-09-19T08:46:00.001-04:002011-11-03T04:34:58.008-04:00Print a NUL-terminated string with awkI thought it would have been easier to print a NUL-terminated string in awk (mawk as it's the default in Debian), but after some trial-and-fail I was able to come up with this kinda ugly solution:<br />
<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$ echo -e "123\n456" | awk 'BEGIN { ORS="" } { print $0 ; printf("%c", "") }' | xargs -n1 -0 echo </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">123</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">456</span><br />
<br />
That:<br />
<br />
<ul><li>set the Output Records Separator (<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">ORS</span>) to the empty string (default is the <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">\n</span>, new line)</li>
<li>print the input line (do your elaboration there, if you need)</li>
<li>print the null character, as explained in the mawk manpage: "<i>mawk cannot handle ascii NUL \0 in the source or data files. You can output NUL using printf with %c, and any other 8 bit character is acceptable input.</i>"</li>
<li>show that it's actually emitting NUL-terminated strings</li>
</ul><div>There's really no better way to do that?</div>Sandro Tosihttp://www.blogger.com/profile/17077191422205823991noreply@blogger.com1