Exemple #1
0
def get_json_content_by_path(bucket, path, force_dict=False):
    raw_content = get_raw_content_by_path(bucket, path)
    if not raw_content:
        return {}
    try:
        result = json_loads(raw_content)
        if force_dict and not isinstance(result, dict):
            return {}
        return result
    except:
        return {}
Exemple #2
0
def from_json(obj):
    # 将一个字符串,重新载入为一个dict/list等类型的py 数据
    if not obj:
        return obj
    if not isinstance(obj, string_types) and hasattr(obj, 'core'):
        # 可能是 Text/ Date 等wrap后的数据对象
        obj = obj.core
    if isinstance(obj, string_types):
        try:
            return json_loads(obj)
        except:
            return obj
    return obj
Exemple #3
0
    def sync(self):
        # one record only, push to server  now
        # return sync_status
        json_data = self.json_data_for_sync
        if not json_data:
            return None  # ignore

        py_data = json_loads(json_data)

        sync_status = self.send_message(action='create', message=json_data)

        # 上传文件
        if py_data.get('_type') in ['file', 'image']:
            raw_file_data = py_data.get('raw_content')
            if not raw_file_data:
                # 直接上传文件, 如果 version 一样,或者 size 超了,都会返回 no 的结果
                reply = self.send_message(action='should_upload_file',
                                          message=json_data)
                if reply.get('message') == 'yes' and os.path.isfile(
                        self.filepath):
                    file_size = os.path.getsize(self.filepath)

                    request_timeout = 120
                    if file_size:
                        file_mb = int(file_size / 1024. / 1024)
                        if file_mb > 2:
                            request_timeout = file_mb * 60  # 1mb 就是多 1 分钟的 timeout
                        request_timeout = min(request_timeout,
                                              30 * 60)  # 不能超过 30 分钟

                    with open(self.filepath, 'rb') as f:
                        sync_status = self.send_message(
                            action='upload_file',
                            message=json_data,
                            file_to_post=f,
                            timeout=request_timeout,
                        )

        if DEBUG:
            info = 'is_deleted=%s, sync %s, sync_status: %s' % (
                self.is_deleted, self.relative_path, sync_status)
            print(info)

        return sync_status
Exemple #4
0
def ssdb_data_to_py_data(ssdb_data, hit_cache=False):
    # 为了避免从 ssdb 中获得数据,反复转为 python 中使用, 增加了 cache_id 的逻辑,以避免重复计算性能消耗的问题
    if not isinstance(ssdb_data, string_types):
        return ssdb_data
    if hit_cache:
        data_cache_key = to_md5(ssdb_data)
        cached_value = ssdb_data_to_py_data_cache.get(data_cache_key)
        if cached_value:
            return cached_value
    else:
        data_cache_key = None
    if re.match('\s*[\[\{\(]', ssdb_data):  # dict list tuple
        try:
            py_data = json_loads(ssdb_data)
            if data_cache_key:
                ssdb_data_to_py_data_cache[data_cache_key] = py_data
        except:
            py_data = to_unicode(ssdb_data)
    else:
        py_data = to_unicode(ssdb_data)
    return py_data
Exemple #5
0
def get_compiler_data_directly(relative_path,
                               content=None,
                               is_deleted=False,
                               is_dir=False,
                               real_relative_path=None):
    if not relative_path:
        return
    if content and len(content) > MAX_RECORD_SIZE:
        # 避免不必要的内存占用,此时的 content 必然不会存储在 raw_content 这个字段中
        content = None
    compiler_worker = FarBoxSyncCompilerWorker(
        server_node=None,
        root=None,
        filepath=None,
        relative_path=relative_path,
        raw_content=content,
        is_deleted=is_deleted,
        is_dir=is_dir,
        real_relative_path=real_relative_path)
    json_data = compiler_worker.json_data_for_sync
    if json_data:
        data = json_loads(json_data)
        return data
def get_normal_data_by_simple_token(bucket,
                                    encrypted_data,
                                    force_py_data=True,
                                    default_if_failed=None):
    # force_py_data = True 的时候,必须是 list/tuple/dict 的数据类型
    if not encrypted_data:
        return encrypted_data
    token = get_simple_bucket_token(bucket)
    if token and isinstance(encrypted_data, string_types):
        result = simple_decrypt(encrypted_data, token)
        try:
            result = json_loads(result)
        except:
            pass
    else:
        result = encrypted_data
    if force_py_data:
        if isinstance(result, (list, tuple, dict)):
            return result
        else:
            return default_if_failed
    else:
        return result
Exemple #7
0
def create_record(bucket,
                  record_data,
                  avoid_repeated=True,
                  auto_id=True,
                  file_content=None,
                  return_record=False):
    # make sure the bucket is correct before create record
    # 如果返回数据,就是 error_info
    # avoid_repeated 就是避免跟最后一条数据 body 是一样的
    error_info = get_record_data_error_info(record_data)
    if error_info:
        return error_info

    py_record_data = ssdb_data_to_py_data(record_data)
    byte_record_data = py_data_to_ssdb_data(record_data)

    if auto_id:
        object_id = str(ObjectId())
        if '_id' not in py_record_data and isinstance(
                py_record_data, dict):  # record data 如有必要自动填充 _id
            py_record_data['_id'] = object_id
    else:
        object_id = py_record_data.get('_id') or py_record_data.get('id')
        avoid_repeated = False  # 指定的 id 的,不做 repeated 的校验
        if not object_id:
            return 'auto_id disabled, should pass id in the record data'

    if avoid_repeated:  # 避免最后一条记录的重复
        record_md5 = to_md5(byte_record_data)
        if not allowed_to_create_record_in_bucket(bucket, record_md5):
            error_info = 'current data is repeated to latest record @%s' % bucket
            if isinstance(py_record_data, dict):
                path_in_record = py_record_data.get('path')
                if path_in_record:
                    error_info += smart_unicode(', the path is %s' %
                                                path_in_record)
            return error_info
        else:
            update_bucket_last_record_md5(bucket, record_md5)

    # '_auto_clean_bucket' in record_data and is `True`
    # 如果是 delete 的直接删除 (break),反之则是完全的 update,相当于新的 record 代替 旧的  record
    auto_clean_status = auto_clean_record_before_handle_path_related_record(
        bucket, py_record_data)
    if auto_clean_status == 'break':
        return

    # store pre_object_id
    # 获得上一个对象的 id, 将当前的 data 转为 dict (如果是),存储 _pre_id 这个字段
    pre_object_id = get_bucket_max_id(bucket)
    if pre_object_id:
        if isinstance(py_record_data, dict):
            py_record_data['_pre_id'] = pre_object_id

    # 存储 record, 并且更新 bucket 上 max_id 的信息
    # 由于 record_id 是随机生成,本质上不会重复,故 ignore_if_exists=False, 避免一次校验的过程
    hset(bucket, object_id, py_record_data, ignore_if_exists=False)

    after_record_created(bucket,
                         py_record_data,
                         object_id=object_id,
                         should_update_bucket_max_id=True)

    # 更新 buckets 的信息,表示当前 bucket 刚刚被更新过了
    set_bucket_into_buckets(bucket)
    if py_record_data.get("path"):
        # path 相关的,因为有 delete 的关系,单独进行 last_record_id 的存储,不然直接 hget_max 就可以了
        set_bucket_last_record_id(bucket, object_id)

    if file_content and not py_record_data.get("raw_content"):
        # 指定了要存储的 file content,并且 record 中并没有 raw_content 这个字段,进行文件的存储
        storage.accept_upload_file_from_client(
            bucket, py_record_data, get_raw_content_func=file_content)

    if py_record_data.get("path") == "settings.json" and py_record_data.get(
            "raw_content"):
        try:
            site_settings = json_loads(py_record_data.get("raw_content"))
            if isinstance(site_settings, dict):
                set_bucket_configs(bucket, site_settings, config_type="site")
        except:
            pass

    if return_record:
        return py_record_data