class Monitor(object): """ Monitor is main class representing web change monitor. It serves as factory for creating MonitoredResource objects. Usage: >>> from rrslib.web.changemonitor import Monitor >>> monitor = Monitor(user_id="rrs_university") >>> resource = monitor.get("http://www.google.com") >>> # if the page changed >>> if resource.check(): >>> print res.get_diff(start='last', end='now') """ def __init__(self, user_id, db_host="localhost", db_port=27017, db_name="webarchive", http_proxy=None): """ Create a new monitor connected to MongoDB at *db_host:db_port* using database db_name. @param user_id: identification string of user/module who uses monitor. If user_id is given None, the monitor switches to `global-view` mode and all requests to storage don't care about >>who checked this resource<<. On the other hand, if user_id is given a string, the monitor switches to `user-view` mode and all operations are oriented to the user. Most of the reasonable use cases are using user_id, because a user/module almost everytime ask about >>what changed since I have been here for the last time<<, not >>what changed since somebody has been here for the last time<<... @type user_id: str or None @param db_host: (optional) hostname or IP address of the instance to connect to, or a mongodb URI, or a list of hostnames / mongodb URIs. If db_host` is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) @param db_port: (optional) port number on which to connect @type db_port: int @param db_name: name of database which is used to store information about monitored documents and their versions. @type db_name: str @param http_proxy: (FUTURE USE) proxy server where to send requests @type http_proxy: unknown """ if not isinstance(user_id, basestring) and user_id is not None: raise TypeError("User ID has to be type str or None.") # save user id self._user_id = user_id # for future use if http_proxy is not None: raise NotImplementedError("HTTP proxy not supported yet.") # initialize models self._init_models(db_host, db_port, db_name, user_id) def _init_models(self, host, port, db, uid): self._conn = Connection(host, port) self._storage = Storage(self._conn, uid, db) self._dbname = db self._dbport = port self._dbhost = host def get(self, url): """ Creates new MonitoredResource instance which represents document on *url*. @param url: URL of monitored resource @type url: str @returns: monitored resource object bound to URL *url*. @rtype: MonitoredResource Design pattern: factory method. """ # test the url validity parse_result = urlparse(url) if parse_result.netloc == '': raise ValueError("URL '%s' is not properly formatted: missing netloc." % url) if parse_result.scheme == '': raise ValueError("URL '%s' is not properly formatted: missing scheme." % url) # return monitored resource object return MonitoredResource(parse_result.geturl(), self._user_id, self._storage) def allow_large_documents(self): """ Allow large objects to be stored in the storage. Large document is defined as file larger than 4096KB. Tis constant is defined in this module named as LARGE_DOCUMENT_SIZE representing size of the file in kilobytes. """ try: # just delegate to storage model self._storage.allow_large_documents() except AttributeError: raise RuntimeError("Models arent initialized. Something went to hell...") def check_uid(self): """ Check if user id given in constructor is a valid user id within the Monitor storage system. If the UID is occupied, returns False, True otherwise. If user_id is None, an exception UidError is raised. @returns: True if the UID is free @rtype: bool """ if self._user_id is None: raise UidError("Cannot check uid=None. Monitor is switched to global-view mode.") return self._storage.check_uid() def check_multi(self, urls=[]): """ Check list of urls, start new thread for each one. @param urls: @type urls: list @returns: list of MonitoredResource objects, each with actual data @rtype: list<MonitoredResource> """ # TODO: zkontrolovat, jestli vsechny prvky v urls jsou validni URL adresy raise NotSupportedYet() def __repr__(self): return "Monitor(conn=%s, dbname='%s', uid='%s')" % \ (self._conn.connection, self._dbname, self._user_id) __str__ = __repr__
def _init_models(self, host, port, db, uid): self._conn = Connection(host, port) self._storage = Storage(self._conn, uid, db) self._dbname = db self._dbport = port self._dbhost = host
def save(): if g.user.role_id == 3: return 'Powerless' sql = '' para = Api.reqs('catalog_id,part,id,sn,username,location,state,description,' 'remark,type,exit,attr1,attr2') para.update({ # 不填默认今天 'purchase_date': request.form.get('purchase_date') or datetime.datetime.today().strftime('%Y-%m-%d'), # 不填默认0元 'price': request.form.get('price') or 0, # 不填默认今天 'register_date': request.form.get('register_date') or datetime.datetime.today().strftime('%Y-%m-%d'), 'engname': g.user.username}) # 批量返还 ids = request.form.getlist('ids') if len(ids): for i in ids: para['id'] = i sql = u"call history_p(:id, '仓库', '仓库', '0', :register_date, :engname);" db.session.execute(sql, para) db.session.commit() return u'批量返还ok' if para['type'] == 'update': sql = ''' UPDATE stdb.storage st SET st.state=:state, st.sn=:sn, st.price=:price, st.description=:description, st.catalog_id=:catalog_id, st.remark=:remark, st.part=:part, st.purchase_date=:purchase_date, {0} st.modify_date=now(), st.modify_user=:engname WHERE st.id=:id '''.format('st.username=:username,st.location=:location,' if g.user.role_id == 1 else '') elif para['type'] == 'insert': checkid = Storage.query.filter_by(id=para['id']).all() if len(checkid): return 'exist' # 笔记本&主机类型 if para['attr1'] or para['attr2']: power = Catalog.query.filter_by(catalog=u'电源适配器').first().id mouse = Catalog.query.filter_by(catalog=u'鼠标').first().id keyboard = Catalog.query.filter_by(catalog=u'键盘').first().id special_ct = Catalog.query.filter_by(id=para['catalog_id']).first().catalog if special_ct in [u'笔记本电脑', u'主机']: obj = [ Storage(id=para['id'], username=u'仓库', state=para['state'], sn=para['sn'], price=para['price'], part=para['part'], description=para['description'], catalog_id=para['catalog_id'], remark=para['remark'], purchase_date=para['purchase_date'], location=u'仓库', create_user=para['engname']), Storage(id=para['id'] + '-01', username=u'仓库', state=para['state'], sn=para['sn'], part=para['part'] + (u'-电源适配器' if special_ct == u'笔记本电脑' else u'-鼠标'), catalog_id=power if special_ct == u'笔记本电脑' else mouse, remark=para['remark'], price=0, description=para['description'], purchase_date=para['purchase_date'], location=u'仓库', create_user=para['engname']) if para['attr1'] else None, Storage(id=para['id'] + '-02', username=u'仓库', state=para['state'], sn=para['sn'], part=para['part'] + (u'-鼠标' if special_ct == u'笔记本电脑' else u'-键盘'), catalog_id=mouse if special_ct == u'笔记本电脑' else keyboard, remark=para['remark'], description=para['description'], price=0, purchase_date=para['purchase_date'], location=u'仓库', create_user=para['engname'] if para['attr2'] else None) ] db.session.add_all([i for i in obj if i]) db.session.commit() return 'ok' else: sql = u''' INSERT INTO stdb.storage (id,username,state,sn,price,description,catalog_id,remark,part,purchase_date,location,create_user,create_date) VALUE (:id,'仓库',:state,:sn,:price,:description,:catalog_id,:remark,:part,:purchase_date,'仓库',:engname,now()) ''' elif para['type'] == 'history': if para['location'] == u'仓库' and para['exit'] == '1': return 'inactive' sql = u'call history_p(:id, :username, :location, :exit, :register_date,:engname);' db.session.execute(sql, para) db.session.commit() return 'ok'