Highlight

2014-04-17

Using SharePoint 2010's REST API

Get 100 items after the first 100 items from the items of this year and month:

http://site.company.tld/_vti_bin/ListData.svc/YourList?$skip=100&$top=100&$select=Year,Month,ID&$filter=Year%20eq%20%272014%27%20and%20Month%20eq%20%27Mar%27


Here's a complete example in Python, TestSharePoint2010REST.py:

"""
SharePoint2010 REST test app by Cees Timmerman, 24jun14.
"""
# Fix Python 2.
from __future__ import print_function
try: input = raw_input
except: pass
try: import urllib.request as urllib2
except: import urllib2
try: from ntlm3 import HTTPNtlmAuthHandler
except: from ntlm import HTTPNtlmAuthHandler

import json, re, time

web_domain = "http://subdomain.company.tld/"
user = "company\\user"
password = "secret"
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, web_domain, user, password)
auth_NTLM = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passman)
opener = urllib2.build_opener(auth_NTLM)
urllib2.install_opener(opener)

url = web_domain + "_vti_bin/ListData.svc/TimeRegistration?$filter=Modified%20gt%20datetime\'2014-04-30T00:00:00.000Z\'&$orderby=Modified%20asc&$select=Id,Year,Month,Hours,Project,Resource&$top=2050"

months = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(",")
count = 0
while 1:
  print(url)
  request = urllib2.Request(url)
  request.add_header("accept", "application/json;odata=verbose")  # The default format is application/atom+xml. Example: "accept":"application/json;odata=verbose"
  response = urllib2.urlopen(request)
  headers = response.info()
  body = response.read().decode("utf-8")
  body = re.sub(r"(?<!\\)\\'", "'", body)  # Fix MicrosoftSharePointTeamServices 14.0.0.6029's incorrect JSON output. http://stackoverflow.com/questions/24390258/json-module-bug-in-python-3-4-1/24390987#comment37724338_24390290
  print("Headers: {}".format(headers))
  print("Body start: " + body[:800])
  print("==========================\nBody end: " + body[-800:])
  #err_loc=314020; print(">>>>>>Parse Error: {}<<<<<<".format(body[err_loc-40:err_loc+40])) # Debug output using value from thrown error.
  j = json.loads(body)
  results = j['d']['results'] if 'results' in j['d'] else j['d']
  print("Len: %r" % len(results))
  for item in results:
    count += 1
    print(item['Resource'].replace("company\\", ""), item['Project'], float(item['Hours']), "{}-{:02}-01".format(item['Year'], 1+months.index(item['Month'])), item['Id'])
  print("Count: %s" % count)
  
  # End loop or process next batch of 1000.
  url = None
  try: url = j['d']['__next']
  except: pass
  if not url: break

2014-03-21

Patching bugs with SVN

I'm using Suds to work with SharePoint, but it was terribly slow due to broken caching, so i patched it:
I:\>cd temp

I:\temp>mkdir sudssvn

I:\temp>cd sudssvn

I:\temp\sudssvn>svn co http://svn.fedorahosted.org/svn/suds/trunk
A    trunk\LICENSE
A    trunk\tests
A    trunk\tests\rhq.py
A    trunk\tests\public.py
...

I:\temp\sudssvn>"C:\Program Files (x86)\Notepad++\notepad++.exe" trunk\suds\cache.py

I:\temp\sudssvn>svn di trunk
Index: trunk/suds/cache.py
===================================================================
--- trunk/suds/cache.py (revision 712)
+++ trunk/suds/cache.py (working copy)
@@ -190,7 +190,7 @@
     def put(self, id, bfr):
         try:
             fn = self.__fn(id)
-            f = self.open(fn, 'w')
+            f = self.open(fn, 'wb')
             f.write(bfr)
             f.close()
             return bfr
@@ -223,7 +223,7 @@
         try:
             fn = self.__fn(id)
             self.validate(fn)
-            return self.open(fn)
+            return self.open(fn, 'rb')
         except:
             pass

I:\temp\sudssvn>svn ci trunk
svn: E205007: Commit failed (details follow):
svn: E205007: Could not use external editor to fetch log message; consider setting the $SVN_EDITOR environment variable or using the --message (-m) or --file (-F) options
svn: E205007: None of the environment variables SVN_EDITOR, VISUAL or EDITOR are set, and no 'editor-cmd' run-time configuration option was found

I:\temp\sudssvn> ...TortoiseSVN GUI:

Commit
Commit failed (details follow):
Can't create directory '/svn/suds/db/transactions/712-1.txn': Permission denied
Alas, a lack of project time/leadership stifles progress, but at least open source and free speech allows one to fork unmaintained projects. Torvalds' Git (simple guide) was made for decentralized development like that.

A Google result (and on closer inspection, previous error) tells me that instead of the GUI, i could've used the -m switch of svn:
I:\temp\sudssvn>svn ci trunk -m "fix caching on Windows"
svn: E000013: Commit failed (details follow):
svn: E000013: Can't create directory '/svn/suds/db/transactions/712-1.txn': Permission denied
The system environment variable PATH gives me easy access to "C:\Program Files\TortoiseSVN\bin\svn.exe".

2014-03-01

Genderswap any webpage!

After trying to read the dismal The Claiming of Sleeping Beauty again, i thought it might be interesting to see whether it'd be more palatable with reversed genders. A difficult experience. Here's the code, which you can set as a bookmark location, then click the bookmark to transform the current page:

javascript:(function(){function swap(txt, a, b){return txt.split(a).join("SWPTMP").split(b).join(a).split("SWPTMP").join(b)};var subs=[[' he ',' she '],[' he\'',' she\''],['He ','She '],[' man ',' woman '],[' men',' women'],['boy','girl'],['King','Queen'],['Lord','Lady'],[' daughter',' son'],['father','mother'],['uncle','aunt'],['Prince','Princess'],[' herself',' himself'],[' her.',' him.'],[' her,',' him,'],[' her a ',' him a '],[' her an ',' him an '],[' her and ',' him and '],[' him to',' her to'],[' him up',' her up'],[' him down',' her down'],[' him again',' her again'],[' him until',' her until'],[' him w',' her w'],[' him by',' her by'],[' her ',' his '],['His ', 'Her ']];t=document.body.innerHTML;for(var i=0;i<subs.length;++i)t=swap(t, subs[i][0], subs[i][1]);document.body.innerHTML=t.replace('Princessss','Prince')})()

2014-02-28

T-SQL: Work Days per Month

Based on http://stackoverflow.com/a/252532/819417

ALTER FUNCTION dbo.fn_WorkDays(@StartDate DATETIME) RETURNS INT
AS
BEGIN
    IF @StartDate IS NULL
        RETURN NULL

    --Strip the time element from both dates (just to be safe) by converting to whole days and back to a date.
    --Usually faster than CONVERT.
    --0 is a date (01/01/1900 00:00:00.000)
    SELECT @StartDate = DATEADD(dd, DATEDIFF(dd, 0, @StartDate), 0)
   
    DECLARE @EndDate DATETIME
    SELECT @EndDate = dateadd(day, -1, dateadd(month, 1, @StartDate))

    RETURN (SELECT        --Start with total number of days including weekends
        (DATEDIFF(dd, @StartDate, @EndDate)+1)
        --Subtract 2 days for each full weekend
        -(DATEDIFF(wk, @StartDate, @EndDate)*2)
        -(CASE WHEN DATEPART(dw, @StartDate) = 1 THEN 1 ELSE 0 END)
        -(CASE WHEN DATEPART(dw, @EndDate) = 7 THEN 1 ELSE 0 END))
END

2013-10-11

US Fusion Energy Lab Achieves Positive Energy Reaction

In late September, American scientists got more energy out of a fusion reaction than the fuel absorbed in igniting it — the first time that’s been achieved by researchers anywhere in the world. The research team that pulled it off is based at the National Ignition Facility (NIF), in Livermore, California. And in a bitter twist, they were furloughed just days afterward by the government shutdown.
http://thinkprogress.org/climate/2013/10/10/2760911/american-researchers-fusion-breakthrough/

Since 1953, when the fusion program started, the total spent on fusion energy in the US, both Magnetic and Inertial is $22.4 billion dollars. Adjusting for inflation, total fusion spending is $29.1 billion. That’s for 57 years of fusion funding. That’s an average of $510 million per year.http://focusfusion.org/index.php/site/reframe/wasteful

The U.S. federal government spent over $15 billion dollars in 2010 on the War on Drugs, at a rate of about $500 per second. State and local governments spent at least another 25 billion dollars.

http://www.drugsense.org/cms/wodclock

2013-10-03

IE8 is Evil.

>>var d = {1:"one", 2:"two",}
  "Expected identifier, string or number"
But that works in IE9's IE8 mode!

Fortunately IE10 does reproduce this bug; too bad IE9 won't upgrade on this Windows 7 machine due to DLL hell. Good thing i have remote desktops:
>>var d = {1:"one", 2:"two"}
undefined
>>d
{...}
That also works in IE8. Bug solved!

But wait, there's more! IE10's IE8 mode happily skips over
var approved_headcount = {
 "ICT": {201301: 1, 201302: 2, 2013.03: 3, 201304: 1, 201305: 2, 201306: 3},
 "Finance": {201301: 1, 201302: 2, 201303: 3, 201304: 1, 201305: 2, 201306: 3},
}
and is thus buggy at being buggy.

I guess they incinerated the IE8 parser as it also returns incorrect line numbers while parsing that code block.

2013-03-05

Digits to Excel column letters

A little tricky, so i'll note it here:

>>> def getLetters(n):
...     o = ""
...     while 1:
...             n, m = divmod(n-1, 26)
...             o = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[m] + o
...             if n < 1: break
...     return o
...
>>> getLetters(1)
'A'
>>> getLetters(25)
'Y'
>>> getLetters(26)
'Z'
>>> getLetters(27)
'AA'

And i might as well include my old getCol function:

def getCol(s):
 z = 0
 for i in range(1, len(s) + 1):
  c = s[-i]
  z += ("ABCDEFGHIJKLMNOPQRSTUVWXYZ".find(c) + 1) * 26**(i - 1)
 return z