1

Okay, I'm stuck. I have been trying to load a file with a serialized string from Aura's save feature and get into an object to work with it.

The file looks like this:


 PkgState {timeOf = SimpleTime {yearOf = 2013, monthOf = February, dayOf = 13, hourOf = 15, minuteOf = 38}, pkgsOf = fromList [("a52dec",[0,7,4,6]),("aalib",[1,4,5,9]),("abs",[2,4,4,1]),("acl",[2,2,51,3]),("acsccid",[1,0,4,1]),("alsa-lib",[1,0,26,1]),("alsa-oss",[1,0,25,1]),("alsa-plugins",[1,0,26,1]),("alsa-utils",[1,0,26,1]),("alsaequal",[0,6,7]),("android-sdk-platform-tools",[16,0,1,2]),("android-udev",[1,6,1]),("anki-beta",[2,0,7,1]),("apache",[2,2,23,1]),("apr",[1,4,6,1]),("apr-util",[1,5,1,1]),("archey",[20121216,1]),("archlinux-keyring",[20130127,1]),("archlinux-themes-slim",[1,2,3]),("aria2",[1,16,3,1]),("asciidoc",[8,6,8,1]),("aspell",[0,60,6,1,1]),("aspell-en",[7,1,2]),("at-spi2-atk",[2,6,2,1]),("at-spi2-core",[2,6,3,1]),("atk",[2,6,0,1]),("attr",[2,4,46,2]),("aura",[1,1,3,0,1]),("autoconf",[2,69,1]),("autofs",[5,0,7,1]),("automake",[1,13,1,1]),("avahi",[0,6,31,5]),("babl",[0,1,10,1]),("bash",[4,2,42,3]),("bc",[1,6,8]),("beecrypt",[4,2,1,5]),("binutils",[2,23,1,3]),("bison",[2,7,1]),("blueman",[1,23,5]),("bluez",[4,101,1]),("bridge-utils",[1,5,1]),("bzip2",[1,0,6,4]),("c-ares",[1,9,1,1]),("ca-certificates",[20130119,1]),("ca-certificates-java",[20120608,1]),("cackey",[0,6,8,1]),("cairo",[1,12,12,2]),("cairo-perl",[1,82,2]),("caps",[0,9,6,1]),("cdparanoia",[10,2,4]),("cdrdao",[1,2,3,6]),("cdrkit",[1,1,11,2]),("chromium",[24,0,1312,70,1]),("chromium-pepper-flash",[11,6,602,167,1]),("cifs-utils",[5,9,1]),("cloog",[0,18,0,1])}

This has been cut down. I can parse it out manually (which would more then likely a pain). Is there some directly to start with this and get an object?

Or since Aura was written in haskell should I just use haskell?

jmac
  • 7,078
  • 2
  • 29
  • 57
flamusdiu
  • 1,722
  • 2
  • 14
  • 31

1 Answers1

2

I suggest the best thing is to make aura save in a JSON format instead of using the Show and Read instances. This might not be any easier than making a one-off parser in Python but it will be a more lasting community change. EDIT: If it isn't obvious, my opinion is it would be truly best to just use Haskell so all you need to do is fmap read (readFile path) to parse, but I'm accustom to that not being a practical option for many programmers with a short time-line.

Step 1: Get the aura code

git clone https://github.com/fosskers/aura.git
cd aura

Step 2: Find where it serealizes something named PkgState:

grep 'writeFile' * -R

Step 3: modify the format (which is currently using show) to using JSON via the aeson package:

+{-# LANGUAGE OverloadedStrings #-}
+import qualified Data.ByteString.Lazy.Char8 as BL
+ import Data.Aeson
...
- liftIO $ writeFile filename (show state)
+ liftIO $ BL.writeFile filename (encode state)

Step 4: Step 3 really isn't done, we need ToJSON instances for that call to encode to work.

+{-# LANGUAGE OverloadedStrings #-}
+ import Data.Aeson
+ instance ToJSON PkgState of
+     toJSON (PkgState t p) = object [ "timeOf" .= t, "pkgsOf" .= p ]

and in Aura/Time.hs:

+ {-# LANGUAGE OverloadedStrings #-} 
...    
+ import Data.Aeson
...
+ instance ToJSON SimpleTime of
+      toJSON (SimpleTime y m d h n) = object [ "yearOf"   .= y
+                                            , "monthOf"  .= fromEnum m
+                                            , "dayOf"    .= d
+                                            , "hourOf"   .= h
+                                            , "minuteOf" .= n
+                                            ]

Step 5: To make this build we need to add the aeson package to the build-deps in aura.cabal.

Step 6: This might work as is for your purposes, but it would be best to make aura able to load files that were JSON encoded:

-import Data.Maybe      (mapMaybe)
+import Data.Maybe      (mapMaybe, fromMaybe)
+import Control.Applicative
+import Control.Monad

...

+instance ToJSON PkgState where
+    toJSON (PkgState t p) = object [ "timeOf" .= t, "pkgsOf" .= p ]
+
+instance FromJSON PkgState where
+    parseJSON (Object v) = PkgState <$> v .: "timeOf" <*> v .: "pkgsOf"
+    parseJSON _ = mzero
+

...

-readState name = liftIO (read `liftM` readFile (stateCache </> name))
-
+readState name = liftIO ((fromMaybe err . decode) `liftM` BL.readFile (stateCache </> name))
+  where err = error "Package State unrecognized"

and again in Aura/Time.hs

+
+instance FromJSON SimpleTime where
+    parseJSON (Object v) = SimpleTime <$> v .: "yearOf"
+                                      <*> (toEnum `fmap` (v .: "monthOf"))
+                                      <*> v .: "dayOf"
+                                      <*> v .: "hourOf"
+                                      <*> v .: "minuteOf"
+

I'll leave the python decoding of this JSON object to you.

Thomas M. DuBuisson
  • 64,245
  • 7
  • 109
  • 166
  • Thanks! I'll look at doing this. I am not familiar with haskell and this is really just learning for me. Hopefully I will get a chance to set this up in the next day or so to see if this will work for my needs. – flamusdiu Feb 14 '13 at 15:57
  • I haven't had a chance to do anything ... life got in the way but I am going to post this on to the github for the project. Edit: accepted your answer since this seems very doable and posted over on the aura github site as well. – flamusdiu Apr 12 '13 at 02:38
  • @framusdiu That's great! Glad you found the post useful. Feel free to steal all the code you'd like. – Thomas M. DuBuisson Apr 13 '13 at 21:35