Commits

Marcin Kasperski  committed e0203a2

Kod nozbowy wyniesiony do mekk.nozbe

  • Participants
  • Parent commits b8ebbc4

Comments (0)

Files changed (3)

File .pydevproject

 <path>/py_mekk_nozbe2xmind/examples</path>
 <path>/py_mekk_nozbe2xmind/script</path>
 </pydev_pathproperty>
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.5</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">MojeDev Python</pydev_property>
 </pydev_project>

File .settings/org.eclipse.core.resources.prefs

-#Fri Dec 19 01:34:18 CET 2008
-eclipse.preferences.version=1
-encoding//src/mekk/nozbe2xmind/context_icons.py=UTF-8
-encoding//src/mekk/nozbe2xmind/xmind_writer.py=UTF-8
+#Sun Nov 08 17:24:56 CET 2009
+eclipse.preferences.version=1
+encoding//src/mekk/nozbe2xmind/context_icons.py=UTF-8
+encoding//src/mekk/nozbe2xmind/nozbe.py=utf-8
+encoding//src/mekk/nozbe2xmind/run.py=utf-8
+encoding//src/mekk/nozbe2xmind/run_analysis.py=utf-8
+encoding//src/mekk/nozbe2xmind/xmind_writer.py=utf-8

File src/mekk/nozbe2xmind/nozbe.py

-# -*- coding: utf-8 -*-
-# (c) 2008, Marcin Kasperski
-
-import twisted.web.client as webclient
-from twisted.internet import defer, reactor
-from simplejson import loads as json_loads, dumps as json_dumps
-import logging
-import base64
-import datetime
-
-log = logging.getLogger("nozbe")
-
-PRODUCTION_URL = "http://www.nozbe.com"
-DEVEL_URL = "http://devl.nozbe.net"
-TIMEOUT = 10 * 60
-
-def getPage(url, contextFactory=None, *args, **kwargs):
-    """
-    twisted.web.client.getPage przepisane odrobinę, by obsłużyć poprawnie
-    ustawianie timeoutów.
-    """
-    scheme, host, port, path = webclient._parse(url)
-    factory = webclient.HTTPClientFactory(url, *args, **kwargs)
-    timeout = kwargs.get('timeout', 30)
-    if scheme == 'https':
-        from twisted.internet import ssl
-        if contextFactory is None:
-            contextFactory = webclient.ssl.ClientContextFactory()
-        reactor.connectSSL(host, port, factory, contextFactory, timeout = timeout)
-    else:
-        reactor.connectTCP(host, port, factory, timeout = timeout)
-    return factory.deferred
-
-
-class NozbeBase(object):
-    """
-    Wspólna część składowa (i konstruktor) dwóch poniższych klas.
-    """
-    def __init__(self, api_key, devel = None):
-        """
-        Inicjalizacja. api_key to klucz dostępu, devel - jeśli niepuste
-        - znaczy używanie środowiska developerskiego i powinno być
-        słownikiem user/password z danymi do autentyfikacji HTTP.
-        """
-        self.key = api_key
-        if not devel:
-            self.url = PRODUCTION_URL
-            self.headers = {}
-        else:
-            self.url = DEVEL_URL
-            assert(type(devel) == dict)
-            basic_auth = base64.encodestring('%(user)s:%(password)s' % devel)
-            auth_header = "Basic " + basic_auth.strip()
-            self.headers = dict(Authorization = auth_header)
-
-    @defer.inlineCallbacks
-    def _make_get_request(self, api_url, *call_items, **params):
-        """
-        Generuje żądanie do Nozbe.
-
-        @param call_items: projects, context albo i actions, what-context
-        @param args: ewentualne specyficzne parametry, np id=cos
-        """
-        url = self._make_url(api_url, *call_items, **params)
-        log.debug("Getting " + url)
-        reply = yield getPage(url, headers = self.headers, timeout = TIMEOUT)
-        if not reply:
-            raise Exception("Can not load data from Nozbe. Wrong API key?")
-        log.debug("Reply: " + reply)
-        data = json_loads(reply)
-        defer.returnValue(data)
-
-    @defer.inlineCallbacks
-    def _make_post_request(self, api_url, *call_items, **params):
-        """
-        Generuje POSTa. Działa identycznie jak _make_get_request, ale wśród params
-        musi być POST=(słownik)
-        """
-        post_text = json_dumps(params['POST'])
-        del params['POST']
-        url = self._make_url(api_url, *call_items, **params)
-        log.debug("Posting " + url + " with " + post_text)
-        reply = yield getPage(url, headers = self.headers, 
-                              method = "POST", postdata = post_text,
-                              timeout = TIMEOUT)
-        if not reply:
-            raise Exception("Can not save data to Nozbe. Wrong API key?")
-        log.debug("Reply: " + reply)
-        data = json_loads(reply)
-        defer.returnValue(data)
-
-    def _make_url(self, api_url, *call_items, **params):
-        parts = [self.url, api_url] + list(call_items) \
-            + [ ("%s-%s" % (key, value)) for key, value in params.iteritems() ] \
-            + [ "key-%s" % self.key ]
-        url = "/".join(parts)
-        if type(url) == unicode:
-            url = url.encode("utf-8")
-        return url
-
-class NozbeLegacyApi(NozbeBase):
-    """
-    @obsolete
-
-    Obsługa pobierania danych z Nozbe przy pomocy *starego* API
-    """
-    api_url = "api"
-
-    def get_projects(self):
-        return self._make_request("projects")
-    def get_contexts(self):
-        return self._make_request("contexts")
-    def get_project_actions(self, project_id):
-        return self._make_request("actions", "what-project", id = project_id)
-
-    def _make_request(self, *call_items, **params):
-        return self._make_get_request(self.api_url, *call_items, **params)
-
-class NozbeSyncApi(NozbeBase):
-    """
-    Obsługa pobierania danych z Nozbe oraz ich zapisu przy pomocy sync-api.
-
-    Funkcje get_* pobierają rozmaite dane, zwracając odpowiednie słowniki i listy słowników.
-
-    Funkcje add_*, delete_* i update_* służą do modyfikacji, ale same niczego nie zmieniają!
-    Lista zmian zapisana przy pomocy sekwencji add_, delete_, update_ zostaje faktycznie
-    wykonana przez wywołanie save_changes.
-    """
-
-    api_url = "sync"
-    app_id = "997"
-
-    RECUR_NO_REPEAT = 0
-    RECUR_EVERY_DAY = 1
-    RECUR_EVERY_WEEKDAY = 2
-    RECUR_EVERY_WEEK = 3
-    RECUR_EVERY_TWO_WEEKS = 4
-    RECUR_EVERY_MONTH = 5
-    RECUR_EVERY_HALF_A_YEAR = 6
-    RECUR_EVERY_YEAR = 7
-
-    recur_labels = {
-        '0' : u"No",
-        '1' : u"Every day",
-        '2' : u"Every weekday",
-        '3' : u"Every week",
-        '4' : u"Every two weeks",
-        '5' : u"Every month",
-        '6' : u"Every half a year",
-        '7' : u"Every year",
-    }
-
-    def __init__(self, api_key, devel = None):
-        NozbeBase.__init__(self, api_key, devel)
-        self._reset_pending_updates()
-        self._update_id = 1
-
-    def get_projects(self):
-        """
-        Zwraca listę projektów. Każdy projekt to słownik o polach
-        - hash,
-        - name,
-        - body,
-        - tag (rozdzielone spacjami),
-        - count (ile akcji nieskończonych),
-        - share (lista współwłaścicieli - name, hash),
-        - ts
-        """
-        return self._get_data("project")
-    def get_contexts(self):
-        """
-        Zwraca listę kontekstów. Słowniki o polach:
-        - hash,
-        - name,
-        - body,
-        - icon,
-        - count (ile niesk. akcji)
-        - ts
-        """
-        return self._get_data("context")
-    def get_tasks(self):
-        """
-        Zwraca listę akcji (zadań). Słowniki o polach:
-        - hash,
-        - name,
-        - name_show, (textile applied)
-        - date     (data zakończenia)
-        - datetime (due date)
-        - recur    (patrz stałe RECUR_)
-        - time     (koszt - czas w minutach)
-        - context_id
-        - context_hash
-        - project_id
-        - project_hash
-        - next     (1 - "next action", 0 - nie)
-        - re_user  (0 gdy odpowiadam ja, inaczej hash innego usera na którym wisi)
-        - ts
-        """
-        return self._get_data("task")
-    def get_completed_tasks(self):
-        """
-        Jak get_tasks ale zwraca zakończone zadania
-        """
-        return self._get_data("task", showdone = "1")
-    def get_notes(self):
-        """
-        Zwraca listę notek. Słowniki:
-        - hash
-        - name
-        - body
-        - body_show
-        - date
-        - context_id
-        - context_hash
-        - project_id
-        - project_hash
-        - ts
-        """
-        return self._get_data("note")
-    def get_uploads(self):
-        """
-        Zwraca listę uploadów. Słowniki:
-        - hash,
-        - name,
-        - date,
-        - size (bajty)
-        - context_id
-        - context_hash
-        - project_id
-        - project_hash
-        - ts
-        """
-        return self._get_data("upload")
-    def get_all(self):
-        """
-        Zwraca słownik o kluczach project, context, task, note, upload, pod każdym kluczem lista
-        taka jak opisana powyżej
-        """
-        return self._make_get_request(self.api_url, "getdata", dev=self.app_id, what="all")
-    def get_ts(self):
-        """
-        Zwraca serwerowy timestamp dla wszystkich rodzajów danych (tj. info kiedy
-        ostatnio były zmieniane). Wynikiem jest hasz o odpowiednich kluczach.
-        """
-        return self._make_get_request(self.api_url, "getts")
-
-    ### Funkcje modyfikujące. Zwracają id dodane do rekordu
-
-    def add_project(self, name, body = "", tag = ""):
-        return self._add_record('project',
-                                dict(name = name, body = body, tag = tag))
-
-    def update_project(self, record):
-        return self._update_record('project', record.copy())
-
-    def delete_project(self, record):
-        return self._delete_record('project', record.copy())
-
-    def add_context(self, name, body = "", icon = ""):
-        return self._add_record('context',
-                                dict(name = name, body = body, icon = icon))
-
-    def update_context(self, record):
-        return self._update_record('context', record.copy())
-
-    def delete_context(self, record):
-        return self._delete_record('context', record.copy())
-
-    def add_tag(self, name):
-        return self._add_record('tag',
-                                dict(name = name))
-
-    def update_tag(self, record):
-        return self._update_record('tag', record.copy())
-
-    def delete_tag(self, record):
-        return self._delete_record('tag', record.copy())
-
-    def add_task(self, name, project_hash, context_hash = "",
-                 date = "", datetime = "", recur = 0, # NozbeSyncApi.RECUR_NO_REPEAT,
-                 time = "5", next = 0):
-        return self._add_record('task',
-                     dict(name = name, project_hash = project_hash, context_hash = context_hash,
-                          date = date, datetime = datetime, recur = recur, time = time, next = next))
-    def update_task(self, record):
-        return self._update_record('task', record.copy())
-
-    def delete_task(self, record):
-        return self._delete_record('task', record.copy())
-
-    def add_note(self, name, body, project_hash, context_hash = "", date = ""):
-        return self._add_record('note',
-                         dict(name = name, body = body,
-                              project_hash = project_hash, context_hash = context_hash, date = date))
-
-    def update_note(self, record):
-        return self._update_record('note', record.copy())
-
-    def delete_note(self, record):
-        return self._delete_record('note', record.copy())
-
-    def _add_record(self, what, record):
-        self._update_id += 1
-        record['id'] = str(self._update_id)
-        self._pending_updates[what].append(record)
-        return record['id']
-
-    def _update_record(self, what, record):
-        self._update_id += 1
-        record['id'] = str(self._update_id)
-        record['flag'] = 'modified'
-        record['ts'] =  datetime.datetime.now().strftime("%Y-%m-%d %T")
-        self._pending_updates[what].append(record)
-        return record['id']
-
-    def _delete_record(self, what, record):
-        self._update_id += 1
-        record['id'] = str(self._update_id)
-        record['flag'] = 'deleted'
-        record['ts'] =  datetime.datetime.now().strftime("%Y-%m-%d %T")
-        self._pending_updates[what].append(record)
-        return record['id']
-
-    def save_changes(self):
-        """
-        Zapisuje wszystkie zmiany przygotowane przy pomocy funkcji add_*, update_*, delete_*
-        """
-        updates = self._pending_updates
-        self._reset_pending_updates()
-        for key in updates.keys():
-            if not updates[key]:
-                del updates[key]
-        return self._make_post_request(self.api_url, "process", dev = self.app_id,
-                                       POST = updates)
-
-    def _reset_pending_updates(self):
-        self._pending_updates = dict(project = [], task = [], context = [], tag = [], note = [])
-
-    @classmethod
-    def recur_label(cls, recur):
-        """
-        Zwraca tekstowy opis danej stałej spośród RECUR_*
-        """
-        return cls.recur_labels[str(recur)]
-
-    @defer.inlineCallbacks
-    def _get_data(self, what, **extra):
-        r = yield self._make_get_request(self.api_url, "getdata", dev=self.app_id, what=what, **extra)
-        defer.returnValue( r[what] )
-
-class NozbeApi(NozbeSyncApi):
-    """
-    Obiekt łączący informacje z obu dostępnych API. Zasadniczo działa jak NozbeSyncApi,
-    ale uzupełnia w niektórych przypadkach zwracane informacje o brakujące dane, które
-    są dostępne tylko via NozbeLegacyApi.
-    """
-    def __init__(self, *args, **kwargs):
-        NozbeSyncApi.__init__(self, *args, **kwargs)
-        self._legacy = NozbeLegacyApi(*args, **kwargs)
-    @defer.inlineCallbacks
-    def get_projects(self):
-        """
-        Zwraca połączone informacje z obu API (zasadniczo dodaje id do projektów)
-        """
-        projects = yield NozbeSyncApi.get_projects(self)
-        leg_projects = yield self._legacy.get_projects()
-        for proj in projects:
-            for lp in leg_projects:
-                if proj['name'] == lp['name']:
-                    proj[u'id'] = lp['id']
-                    break
-            if not proj['id']:
-                log.warn("Couldn't find id for project '%s', link will not be available" % proj['name'])
-        defer.returnValue(projects)
-        
-class CachingNozbeApi(NozbeApi):
-    """
-    Jak NozbeApi, ale cacheuje wyniki funkcji get_projects, get_contexts, get_tasks,
-    get_completed_tasks, get_notes i get_uploads.
-    """
-    def __init__(self, *args, **kwargs):
-        NozbeApi.__init__(self, *args, **kwargs)
-        self._cache = dict()
-    def get_projects(self):
-        return self._get_with_caching("projects", NozbeApi.get_projects)
-    def get_contexts(self):
-        return self._get_with_caching("contexts", NozbeApi.get_contexts)
-    def get_tasks(self):
-        return self._get_with_caching("tasks", NozbeApi.get_tasks)
-    def get_completed_tasks(self):
-        return self._get_with_caching("completed_tasks", NozbeApi.get_completed_tasks)
-    def get_notes(self):
-        return self._get_with_caching("notes", NozbeApi.get_notes)
-    def get_uploads(self):
-        return self._get_with_caching("uploads", NozbeApi.get_uploads)
-    @defer.inlineCallbacks
-    def _get_with_caching(self, name, method, *args, **kwargs):
-        p = self._cache.get(name)
-        if not p:
-            p = yield method(self, *args, **kwargs)
-            self._cache[name] = p
-        defer.returnValue(p)
-