text:
// Monary - Copyright 2011-2014 David J. C. Beach
// Please see the included LICENSE.TXT and NOTICE.TXT for licensing information.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "mongoc.h"
#include "bson.h"

#ifndef NDEBUG
#define DEBUG(format, ...) fprintf(stderr, "[DEBUG] %s:%i " format "\n", __FILE__, __LINE__, __VA_ARGS__)
#else
#define DEBUG(...)
#endif

#define MONARY_MAX_NUM_COLUMNS 1024
#define MONARY_MAX_STRING_LENGTH 1024
#define MONARY_MAX_QUERY_LENGTH 4096

enum {
    TYPE_UNDEFINED = 0,
    TYPE_OBJECTID = 1,
    TYPE_BOOL = 2,
    TYPE_INT8 = 3,
    TYPE_INT16 = 4,
    TYPE_INT32 = 5,
    TYPE_INT64 = 6,
    TYPE_UINT8 = 7,
    TYPE_UINT16 = 8,
    TYPE_UINT32 = 9,
    TYPE_UINT64 = 10,
    TYPE_FLOAT32 = 11,
    TYPE_FLOAT64 = 12,
    TYPE_DATE = 13,      // BSON date-time, seconds since the UNIX epoch (uint64 storage)
    TYPE_TIMESTAMP = 14, // BSON timestamp - UNIX timestamp and increment (uint64 storage)
    TYPE_STRING = 15,    // each record is (type_arg) chars in length
    TYPE_BINARY = 16,    // each record is (type_arg) bytes in length
    TYPE_BSON = 17,      // BSON subdocument as binary (each record is type_arg bytes)
    TYPE_TYPE = 18,      // BSON type code (uint8 storage)
    TYPE_SIZE = 19,      // data size of a string, symbol, binary, or bson object (uint32)
    TYPE_LENGTH = 20,    // length of string (character count) or num elements in BSON (uint32)
    LAST_TYPE = 20       // BSON type code as per the BSON specificaion
};

/**
 * Controls the logging performed by libmongoc.
 */
void monary_log_func (mongoc_log_level_t log_level,
                      const char* log_domain,
                      const char* message,
                      void* user_data)
{
    return;
}

/**
 * Initialize libmongoc.
 */
void monary_init(void) {
    mongoc_init();
#ifdef NDEBUG
    mongoc_log_set_handler(monary_log_func, NULL);
#endif
    DEBUG("%s", "monary module initialized");
}

/**
 * Releases resources used by libmongoc.
 */
void monary_cleanup(void) {
    mongoc_cleanup();
    DEBUG("%s", "monary module cleaned up");
}

/**
 * Makes a new connection to a MongoDB server and database.
 *
 * @param uri A MongoDB URI, as per mongoc_uri(7).
 *
 * @return A pointer to a mongoc_client_t, or NULL if the connection attempt
 * was unsuccessful.
 */
mongoc_client_t* monary_connect(const char* uri) {
    mongoc_client_t* client;
    if (!uri) {
        return NULL;
    }

    DEBUG("Attempting connection to: %s", uri);
    client = mongoc_client_new(uri);
    if (client) {
        DEBUG("%s", "Connection successful");
    }
    else {
        DEBUG("An error occurred while attempting to connect to %s", uri);
    }
    return client;
}

/**
 * Destroys all resources associated with the client.
 */
void monary_disconnect(mongoc_client_t* client)
{
    DEBUG("%s", "Closing mongoc_client");
    mongoc_client_destroy(client);
}

/**
 * Use a particular database and collection from the given MongoDB client.
 *
 * @param client A mongoc_client_t that has been properly connected to with
 * mongoc_client_new().
 * @param db A valid ASCII C string for the name of the database.
 * @param collection A valid ASCII C string for the collection name.
 *
 * @return If successful, a mongoc_collection_t that can be queried against
 * with mongoc_collection_find(3).
 */
mongoc_collection_t* monary_use_collection(mongoc_client_t* client,
                                           const char* db,
                                           const char* collection)
{
    return mongoc_client_get_collection(client, db, collection);
}

/**
 * Destroys the given collection, allowing you to connect to another one.
 *
 * @param collection The collection to destroy.
 */
void monary_destroy_collection(mongoc_collection_t* collection)
{
    if (collection) {
        DEBUG("%s", "Closing mongoc_collection");
        mongoc_collection_destroy(collection);
    }
}

/**
 * Holds the storage for an array of objects.
 *
 * @memb field The name of the field in the document.
 * @memb type The BSON type identifier, as specified by the Monary type enum.
 * @memb type_arg If type is binary, UTF-8, or document, type_arg specifies the
 * width of the field in bytes.
 * @memb storage A pointer to the location of the "array" in memory. In the
 * Python side of Monary, this points to the start of the NumPy array.
 * @memb mask A pointer to the the "masked array." This is the internal
 * representation of the NumPy ma.array, which corresponds one-to-one to the
 * storage array. A value is masked if and only if an error occurs while
 * loading memory from MongoDB.
 */
typedef struct monary_column_item
{
    char* field;
    unsigned int type;
    unsigned int type_arg;
    void* storage;
    unsigned char* mask;
} monary_column_item;

/**
 * Represents a collection of arrays.
 *
 * @memb num_columns The number of arrays to track, one per field.
 * @memb num_rows The number of elements per array. (Specifically, each
 * monary_column_item.storage contains num_rows elements.)
 * @memb columns A pointer to the first array.
 */
typedef struct monary_column_data
{
    unsigned int num_columns;
    unsigned int num_rows;
    monary_column_item* columns;
} monary_column_data;

/**
 * A MongoDB cursor augmented with Monary column data.
 */
typedef struct monary_cursor {
    mongoc_cursor_t* mcursor;
    monary_column_data* coldata;
} monary_cursor;

/**
 * Allocates heap space for data storage.
 *
 * @param num_columns The number of fields to store (that is, the number of
 * internal monary_column_item structs tracked by the column data structure).
 * Cannot exceed MONARY_MAX_NUM_COLS.
 * @param num_rows The lengths of the arrays managed by each column item.
 *
 * @return A pointer to the newly-allocated column data.
 */
monary_column_data* monary_alloc_column_data(unsigned int num_columns,
                                             unsigned int num_rows)
{
    monary_column_data* result;
    monary_column_item* columns;

    if(num_columns > MONARY_MAX_NUM_COLUMNS) { return NULL; }
    result = (monary_column_data*) malloc(sizeof(monary_column_data));
    columns = (monary_column_item*) calloc(num_columns, sizeof(monary_column_item));

    DEBUG("%s", "Column data allocated");

    result->num_columns = num_columns;
    result->num_rows = num_rows;
    result->columns = columns;

    return result;
}

int monary_free_column_data(monary_column_data* coldata)
{
    int i;
    monary_column_item* col;

    if(coldata == NULL || coldata->columns == NULL) { return 0; }

    for(i = 0; i < coldata->num_columns; i++) {
        col = coldata->columns + i;
        if(col->field != NULL) { free(col->field); }
    }
    free(coldata->columns);
    free(coldata);
    return 1;
}

/**
 * Sets the field value for a particular column and item. This is referenced by
 * Monary._make_column_data.
 *
 * @param coldata A pointer to the column data to modify.
 * @param colnum The number of the column item within the table to modify
 * (representing one data field). Columns are indexed starting from zero.
 * @param field The new name of the column item. Cannot exceed
 * MONARY_MAX_STRING_LENGTH characters in length.
 * @param type The new type of the item.
 * @param type_arg For UTF-8, binary and BSON types, specifies the size of the
 * data.
 * @param storage A pointer to the new location of the data in memory, which
 * cannot be NULL. Note that this does not free(3) the previous storage
 * pointer.
 * @param mask A pointer to the new masked array, which cannot be NULL. It is a
 * programming error to have a masked array different in length from the
 * storage array.
 *
 * @return 1 if the modification was performed successfully; 0 otherwise.
 */
int monary_set_column_item(monary_column_data* coldata,
                           unsigned int colnum,
                           const char* field,
                           unsigned int type,
                           unsigned int type_arg,
                           void* storage,
                           unsigned char* mask)
{
    int len;
    monary_column_item* col;

    if(coldata == NULL) { return 0; }
    if(colnum >= coldata->num_columns) { return 0; }
    if(type == TYPE_UNDEFINED || type > LAST_TYPE) { return 0; }
    if(storage == NULL) { return 0; }
    if(mask == NULL) { return 0; }

    len = strlen(field);
    if(len > MONARY_MAX_STRING_LENGTH) { return 0; }

    col = coldata->columns + colnum;

    col->field = malloc(len + 1);
    strcpy(col->field, field);

    col->type = type;
    col->type_arg = type_arg;
    col->storage = storage;
    col->mask = mask;

    return 1;
}

int monary_load_objectid_value(const bson_iter_t* bsonit,
                               monary_column_item* citem,
                               int idx)
{
    const bson_oid_t* oid;
    uint8_t* dest;

    if (BSON_ITER_HOLDS_OID(bsonit)) {
        oid = bson_iter_oid(bsonit);
        dest = ((uint8_t*) citem->storage) + (idx * sizeof(bson_oid_t));
        memcpy(dest, oid->bytes, sizeof(bson_oid_t));
        return 1;
    } else {
        return 0;
    }
}

int monary_load_bool_value(const bson_iter_t* bsonit,
                           monary_column_item* citem,
                           int idx)
{
    bool value;

    value = bson_iter_bool(bsonit);
    memcpy(((bool*) citem->storage) + idx, &value, sizeof(bool));
    return 1;
}

#define MONARY_DEFINE_FLOAT_LOADER(FUNCNAME, NUMTYPE)                        \
int FUNCNAME (const bson_iter_t* bsonit,                                     \
              monary_column_item* citem,                                     \
              int idx)                                                       \
{                                                                            \
    NUMTYPE value;                                                           \
    if (BSON_ITER_HOLDS_DOUBLE(bsonit)) {                                    \
        value = (NUMTYPE) bson_iter_double(bsonit);                          \
        memcpy(((NUMTYPE*) citem->storage) + idx, &value, sizeof(NUMTYPE));  \
        return 1;                                                            \
    } else if (BSON_ITER_HOLDS_INT32(bsonit)) {                              \
        value = (NUMTYPE) bson_iter_int32(bsonit);                           \
        memcpy(((NUMTYPE*) citem->storage) + idx, &value, sizeof(NUMTYPE));  \
        return 1;                                                            \
    } else if (BSON_ITER_HOLDS_INT64(bsonit)) {                              \
        value = (NUMTYPE) bson_iter_int64(bsonit);                           \
        memcpy(((NUMTYPE*) citem->storage) + idx, &value, sizeof(NUMTYPE));  \
        return 1;                                                            \
    } else {                                                                 \
        return 0;                                                            \
    }                                                                        \
}

// Floating point
MONARY_DEFINE_FLOAT_LOADER(monary_load_float32_value, float)
MONARY_DEFINE_FLOAT_LOADER(monary_load_float64_value, double)

#define MONARY_DEFINE_INT_LOADER(FUNCNAME, NUMTYPE)                          \
int FUNCNAME (const bson_iter_t* bsonit,                                     \
              monary_column_item* citem,                                     \
              int idx)                                                       \
{                                                                            \
    NUMTYPE value;                                                           \
    if (BSON_ITER_HOLDS_INT32(bsonit)) {                                     \
        value = (NUMTYPE) bson_iter_int32(bsonit);                           \
        memcpy(((NUMTYPE*) citem->storage) + idx, &value, sizeof(NUMTYPE));  \
        return 1;                                                            \
    } else if (BSON_ITER_HOLDS_INT64(bsonit)) {                              \
        value = (NUMTYPE) bson_iter_int64(bsonit);                           \
        memcpy(((NUMTYPE*) citem->storage) + idx, &value, sizeof(NUMTYPE));  \
        return 1;                                                            \
    } else if (BSON_ITER_HOLDS_DOUBLE(bsonit)) {                             \
        value = (NUMTYPE) bson_iter_double(bsonit);                          \
        memcpy(((NUMTYPE*) citem->storage) + idx, &value, sizeof(NUMTYPE));  \
        return 1;                                                            \
    } else {                                                                 \
        return 0;                                                            \
    }                                                                        \
}

// Signed integers
MONARY_DEFINE_INT_LOADER(monary_load_int8_value, int8_t)
MONARY_DEFINE_INT_LOADER(monary_load_int16_value, int16_t)
MONARY_DEFINE_INT_LOADER(monary_load_int32_value, int32_t)
MONARY_DEFINE_INT_LOADER(monary_load_int64_value, int64_t)

// Unsigned integers
MONARY_DEFINE_INT_LOADER(monary_load_uint8_value, uint8_t)
MONARY_DEFINE_INT_LOADER(monary_load_uint16_value, uint16_t)
MONARY_DEFINE_INT_LOADER(monary_load_uint32_value, uint32_t)
MONARY_DEFINE_INT_LOADER(monary_load_uint64_value, uint64_t)

int monary_load_datetime_value(const bson_iter_t* bsonit,
                               monary_column_item* citem,
                               int idx)
{
    int64_t value;

    if (BSON_ITER_HOLDS_DATE_TIME(bsonit)) {
        value = bson_iter_date_time(bsonit);
        memcpy(((int64_t*) citem->storage) + idx, &value, sizeof(int64_t));
        return 1;
    } else {
        return 0;
    }
}

int monary_load_timestamp_value(const bson_iter_t* bsonit,
                                monary_column_item* citem,
                                int idx)
{
    uint32_t timestamp;
    uint32_t increment;
    char* dest;         // Would be void*, but Windows compilers complain

    dest = (char*) citem->storage + idx*sizeof(int64_t);
    if (BSON_ITER_HOLDS_TIMESTAMP(bsonit)) {
        bson_iter_timestamp(bsonit, &timestamp, &increment);
        memcpy(dest, &timestamp, sizeof(int32_t));
        memcpy(dest + sizeof(int32_t), &increment, sizeof(int32_t));
        return 1;
    } else {
        return 0;
    }
}

int monary_load_string_value(const bson_iter_t* bsonit,
                             monary_column_item* citem,
                             int idx)
{
    char* dest;         // Pointer to the final location of the array in mem
    const char* src;    // Pointer to immutable buffer
    int size;
    uint32_t stringlen; // The size of the string according to iter_utf8

    if (BSON_ITER_HOLDS_UTF8(bsonit)) {
        src = bson_iter_utf8(bsonit, &stringlen);
        size = citem->type_arg;
        if (stringlen > size) {
            stringlen = size;
        }
        dest = ((char*) citem->storage) + (idx * size);
        // Note: numpy strings need not end in \0
        memcpy(dest, src, stringlen);
        return 1;
    } else {
        return 0;
    }
}

int monary_load_binary_value(const bson_iter_t* bsonit,
                             monary_column_item* citem,
                             int idx)
{
    bson_subtype_t subtype;
    const uint8_t* binary;
    int size;
    uint32_t binary_len;
    uint8_t* dest;

    if (BSON_ITER_HOLDS_BINARY(bsonit)) {
        // Load the binary
        bson_iter_binary(bsonit, &subtype, &binary_len, &binary);

        // Size checking
        size = citem->type_arg;
        if(binary_len > size) {
            binary_len = size;
        }

        dest = ((uint8_t*) citem->storage) + (idx * size);
        memcpy(dest, binary, binary_len);
        return 1;
    } else {
        return 0;
    }
}

int monary_load_document_value(const bson_iter_t* bsonit,
                               monary_column_item* citem,
                               int idx)
{
    uint32_t document_len;      // The length of document in bytes.
    const uint8_t* document;    // Pointer to the immutable document buffer.
    uint8_t* dest;

    if (BSON_ITER_HOLDS_DOCUMENT(bsonit)) {
        bson_iter_document(bsonit, &document_len, &document);
        if (document_len > citem->type_arg) {
            document_len = citem->type_arg;
        }

        dest = ((uint8_t*) citem->storage) + (idx * document_len);
        memcpy(dest, document, document_len);
        return 1;
    } else {
        return 0;
    }
}

int monary_load_type_value(const bson_iter_t* bsonit,
                           monary_column_item* citem,
                           int idx) {
    uint8_t type;
    uint8_t* dest;
    type = (uint8_t) bson_iter_type(bsonit);
    dest = ((uint8_t*) citem->storage) + idx;
    memcpy(dest, &type, sizeof(uint8_t));
    return 1;
}

int monary_load_size_value(const bson_iter_t* bsonit,
                           monary_column_item* citem,
                           int idx)
{
    bson_type_t type;
    const uint8_t* discard;
    uint32_t size;
    uint32_t* dest;

    type = bson_iter_type(bsonit);
    switch (type) {
        case BSON_TYPE_UTF8:
        case BSON_TYPE_CODE:
            bson_iter_utf8(bsonit, &size);
            break;
        case BSON_TYPE_BINARY:
            bson_iter_binary(bsonit, NULL, &size, &discard);
            break;
        case BSON_TYPE_DOCUMENT:
            bson_iter_document(bsonit, &size, &discard);
            break;
        case BSON_TYPE_ARRAY:
            bson_iter_array(bsonit, &size, &discard);
            break;
        default:
            return 0;
    }
    dest = ((uint32_t*) citem->storage) + idx;
    memcpy(dest, &size, sizeof(uint32_t));
    return 1;
}

int monary_load_length_value(const bson_iter_t* bsonit,
                             monary_column_item* citem,
                             int idx)
{
    bson_type_t type;
    bson_iter_t child;
    const char* discard;
    uint32_t length;
    uint32_t* dest;

    type = bson_iter_type(bsonit);
    switch (type) {
        case BSON_TYPE_UTF8:
        case BSON_TYPE_CODE:
            discard = bson_iter_utf8(bsonit, &length);
            for (length = 0; *discard; length++) {
                discard = bson_utf8_next_char(discard);
            }
            break;
        case BSON_TYPE_ARRAY:
        case BSON_TYPE_DOCUMENT:
            if (!bson_iter_recurse(bsonit, &child)) {
                return 0;
            }
            for (length = 0; bson_iter_next(&child); length++);
            break;
        case BSON_TYPE_BINARY:
            bson_iter_binary(bsonit, NULL, &length, (const uint8_t**) &discard);
            break;
        default:
            return 0;
    }

    dest = ((uint32_t*) citem->storage) + idx;
    memcpy(dest, &length, sizeof(uint32_t));
    return 1;
}

#define MONARY_DISPATCH_TYPE(TYPENAME, TYPEFUNC)    \
case TYPENAME:                                      \
success = TYPEFUNC(bsonit, citem, offset);          \
break;

int monary_load_item(const bson_iter_t* bsonit,
                     monary_column_item* citem,
                     int offset)
{
    int success = 0;

    switch(citem->type) {
        MONARY_DISPATCH_TYPE(TYPE_OBJECTID, monary_load_objectid_value)
        MONARY_DISPATCH_TYPE(TYPE_DATE, monary_load_datetime_value)
        MONARY_DISPATCH_TYPE(TYPE_TIMESTAMP, monary_load_timestamp_value)
        MONARY_DISPATCH_TYPE(TYPE_BOOL, monary_load_bool_value)

        MONARY_DISPATCH_TYPE(TYPE_INT8, monary_load_int8_value)
        MONARY_DISPATCH_TYPE(TYPE_INT16, monary_load_int16_value)
        MONARY_DISPATCH_TYPE(TYPE_INT32, monary_load_int32_value)
        MONARY_DISPATCH_TYPE(TYPE_INT64, monary_load_int64_value)

        MONARY_DISPATCH_TYPE(TYPE_UINT8, monary_load_uint8_value)
        MONARY_DISPATCH_TYPE(TYPE_UINT16, monary_load_uint16_value)
        MONARY_DISPATCH_TYPE(TYPE_UINT32, monary_load_uint32_value)
        MONARY_DISPATCH_TYPE(TYPE_UINT64, monary_load_uint64_value)

        MONARY_DISPATCH_TYPE(TYPE_FLOAT32, monary_load_float32_value)
        MONARY_DISPATCH_TYPE(TYPE_FLOAT64, monary_load_float64_value)

        MONARY_DISPATCH_TYPE(TYPE_STRING, monary_load_string_value)
        MONARY_DISPATCH_TYPE(TYPE_BINARY, monary_load_binary_value)
        MONARY_DISPATCH_TYPE(TYPE_BSON, monary_load_document_value)

        MONARY_DISPATCH_TYPE(TYPE_SIZE, monary_load_size_value)
        MONARY_DISPATCH_TYPE(TYPE_LENGTH, monary_load_length_value)
        MONARY_DISPATCH_TYPE(TYPE_TYPE, monary_load_type_value)
        default:
            DEBUG("%s does not match any Monary type", citem->field);
            break;
    }

    return success;
}

/**
 * Copies over raw BSON data into Monary column storage. This function
 * determines the types of the data, dispatches to an appropriate handler and
 * copies over the data. It keeps a count of any unsuccessful loads and sets
 * NumPy-compatible masks on the data as appropriate.
 *
 * @param coldata A pointer to monary_column_data which contains the final
 * storage location for the BSON data.
 * @param row The row number to store the data in. Cannot exceed
 * coldata->num_rows.
 * @param bson_data A pointer to an immutable BSON data buffer.
 *
 * @return The number of unsuccessful loads.
 */
int monary_bson_to_arrays(monary_column_data* coldata,
                          unsigned int row,
                          const bson_t* bson_data)
{
    bson_iter_t bsonit;
    bson_iter_t descendant;
    int i;
    int masked;
    int success;
    monary_column_item* citem;

    if (!coldata || !bson_data) {
        DEBUG("%s", "Array pointer or BSON data was NULL and could not be loaded.");
        return -1;
    }
    if (row > coldata->num_rows) {
        DEBUG("Tried to load row %d, but that exceeds the maximum # of rows (%d) ", row, coldata->num_rows);
        return -1;
    }

    masked = 0;
    for (i = 0; i < coldata->num_columns; i++) {
        success = 0;
        citem = coldata->columns + i;

        // Use the iterator to find the field we want
        bson_iter_init(&bsonit, bson_data);
        if (bson_iter_find_descendant(&bsonit, citem->field, &descendant)) {
            success = monary_load_item(&descendant, citem, row);
        }

        // Record success in mask
        if (citem->mask != NULL) {
            citem->mask[row] = !success;
        }
        if (!success) {
            masked++;
        }
    }

    return masked;
}

/**
 * Performs a count query on a MongoDB collection.
 *
 * @param collection The MongoDB collection to query against.
 * @param query A pointer to a BSON buffer representing the query.
 *
 * @return If unsuccessful, returns -1; otherwise, returns the number of
 * documents counted.
 */
int64_t monary_query_count(mongoc_collection_t* collection,
                           const uint8_t* query)
{
    bson_error_t error;     // A location for BSON errors
    bson_t query_bson;      // The query converted to BSON format
    int64_t total_count;    // The number of documents counted
    uint32_t query_size;    // Length of the query in bytes

    DEBUG("%s", "Starting Monary count");

    // build BSON query data
    memcpy(&query_size, query, sizeof(uint32_t));
    if (!bson_init_static(&query_bson,
                          query,
                          query_size)) {
        DEBUG("%s", "Failed to initialize raw BSON query");
        return -1;
    }

    // Make the count query
    total_count = mongoc_collection_count(collection,
                                          MONGOC_QUERY_NONE,
                                          &query_bson,
                                          0,
                                          0,
                                          NULL,
                                          &error);
    bson_destroy(&query_bson);
    if (total_count < 0) {
        DEBUG("error: %d.%d %s", error.domain, error.code, error.message);
    }

    return total_count;
}

/**
 * Given pre-allocated array data that specifies the fields to find, this
 * builds a BSON document that can be passed into a MongoDB query.
 *
 * @param coldata A pointer to a monary_column_data, which should have already
 * been allocated and built properly. The names of the fields of its column
 * items become the names of the fields to query for.
 * @param fields_bson A pointer to a bson_t that should already be initialized.
 * After this BSON is written to, it may be used in a query and then destroyed
 * afterwards.
 */
void monary_get_bson_fields_list(monary_column_data* coldata,
                                 bson_t* fields_bson)
{
    int i;
    monary_column_item* col;

    // We want to select exactly each field specified in coldata, of which
    // there are exactly coldata.num_columns
    for (i = 0; i < coldata->num_columns; i++) {
        col = coldata->columns + i;
        bson_append_int32(fields_bson, col->field, -1, 1);
    }
}

/**
 * Performs a find query on a MongoDB collection, selecting certain fields from
 * the results and storing them in Monary columns.
 *
 * @param collection The MongoDB collection to query against.
 * @param offset The number of documents to skip, or zero.
 * @param limit The maximum number of documents to return, or zero.
 * @param query A pointer to a BSON buffer representing the query.
 * @param coldata The column data to store the results in.
 * @param select_fields If truthy, select exactly the fields from the database
 * that match the fields in coldata. If false, the query will find and return
 * all fields from matching documents.
 *
 * @return If successful, a Monary cursor that should be freed with
 * monary_close_query() when no longer in use. If unsuccessful, or if an
 * invalid query was passed in, NULL is returned.
 */
monary_cursor* monary_init_query(mongoc_collection_t* collection,
                                 uint32_t offset,
                                 uint32_t limit,
                                 const uint8_t* query,
                                 monary_column_data* coldata,
                                 int select_fields)
{
    bson_t query_bson;          // BSON representing the query to perform
    bson_t* fields_bson;        // BSON holding the fields to select
    int32_t query_size;
    monary_cursor* cursor;
    mongoc_cursor_t* mcursor;   // A MongoDB cursor

    // Sanity checks
    if (!collection || !query || !coldata) {
        DEBUG("%s", "Given a NULL param.");
        return NULL;
    }

    // build BSON query data
    memcpy(&query_size, query, sizeof(int32_t));
    query_size = (int32_t) BSON_UINT32_FROM_LE(query_size);
    if (!bson_init_static(&query_bson,
                          query,
                          query_size)) {
        DEBUG("%s", "Failed to initialize raw BSON query");
        return NULL;
    }
    fields_bson = NULL;

    // build BSON fields list (if necessary)
    if(select_fields) {
        fields_bson = bson_new();
        if (!fields_bson) {
            DEBUG("%s", "An error occurred while allocating memory for BSON data");
            return NULL;
        }
        monary_get_bson_fields_list(coldata, fields_bson);
    }

    // create query cursor
    mcursor = mongoc_collection_find(collection,
                                     MONGOC_QUERY_NONE,
                                     offset,
                                     limit,
                                     0,
                                     &query_bson,
                                     fields_bson,
                                     NULL);

    // destroy BSON fields
    bson_destroy(&query_bson);
    if(fields_bson) { bson_destroy(fields_bson); }

    if (!mcursor) {
        DEBUG("%s", "An error occurred with the query");
        return NULL;
    }

    // finally, create a new Monary cursor
    cursor = (monary_cursor*) malloc(sizeof(monary_cursor));
    cursor->mcursor = mcursor;
    cursor->coldata = coldata;
    return cursor;
}

/**
 * Performs an aggregation operation on a MongoDB collection.
 *
 * @param collection The MongoDB collection to query against.
 * @param pipeline A pointer to a BSON buffer representing the pipeline.
 * @param coldata The column data to store the results in.
 *
 * @return If successful, a Monary cursor that should be freed with
 * monary_close_query() when no longer in use. If unsuccessful, or if an invalid
 * pipeline was passed in, NULL is returned.
 */
monary_cursor* monary_init_aggregate(mongoc_collection_t* collection,
                                     const uint8_t* pipeline,
                                     monary_column_data* coldata)
{
    bson_t pl_bson;
    int32_t pl_size;
    mongoc_cursor_t* mcursor;
    monary_cursor* cursor;

    // Sanity checks
    if (!collection) {
        DEBUG("%s", "Invalid collection");
        return NULL;
    }
    else if (!pipeline) {
        DEBUG("%s", "Invalid pipeline");
        return NULL;
    }

    // Build BSON pipeline
    memcpy(&pl_size, pipeline, sizeof(int32_t));
    pl_size = (int32_t) BSON_UINT32_FROM_LE(pl_size);
    if (!bson_init_static(&pl_bson,
                          pipeline,
                          pl_size)) {
        DEBUG("%s", "Failed to initialize raw BSON pipeline");
        return NULL;
    }

    // Get an aggregation cursor
    mcursor = mongoc_collection_aggregate(collection,
                                          MONGOC_QUERY_NONE,
                                          &pl_bson,
                                          NULL,
                                          NULL);

    // Clean up
    bson_destroy(&pl_bson);

    if (!mcursor) {
        DEBUG("%s", "An error occurred with the aggregation");
        return NULL;
    }

    cursor = (monary_cursor*) malloc(sizeof(monary_cursor));
    cursor->mcursor = mcursor;
    cursor->coldata = coldata;
    return cursor;
}

/**
 * Grabs the results obtained from the MongoDB cursor and loads them into
 * in-memory arrays.
 *
 * @param cursor A pointer to a Monary cursor, which contains both a MongoDB
 * cursor and Monary column data that stores the retrieved information.
 *
 * @return The number of rows loaded into memory.
 */
int monary_load_query(monary_cursor* cursor)
{
    bson_error_t error;             // A location for errors
    const bson_t* bson;             // Pointer to an immutable BSON buffer
    int num_masked;
    int row;
    int total_values;
    monary_column_data* coldata;
    mongoc_cursor_t* mcursor;

    mcursor = cursor->mcursor;  // The underlying MongoDB cursor
    coldata = cursor->coldata;  // A pointer to the NumPy array data
    row = 0;                    // Iterator var over the lengths of the arrays
    num_masked = 0;             // The number of failed loads

    // read result values
    while(row < coldata->num_rows
            && !mongoc_cursor_error(mcursor, &error)
            && mongoc_cursor_next(mcursor, &bson)) {

#ifndef NDEBUG
        if(row % 500000 == 0) {
            DEBUG("...%i rows loaded", row);
        }
#endif

        num_masked += monary_bson_to_arrays(coldata, row, bson);
        ++row;
    }

    if (mongoc_cursor_error(mcursor, &error)) {
        DEBUG("error: %d.%d %s", error.domain, error.code, error.message);
    }

    total_values = row * coldata->num_columns;
    DEBUG("%i rows loaded; %i / %i values were masked", row, num_masked, total_values);

    return row;
}

/**
 * Destroys the underlying MongoDB cursor associated with the given cursor.
 *
 * Note that the column data is not freed in this function as that data is
 * exposed as NumPy arrays in Python.
 *
 * @param cursor A pointer to the Monary cursor to close. If cursor is NULL,
 * no operation is performed.
 */
void monary_close_query(monary_cursor* cursor)
{
    if (cursor) {
        DEBUG("%s", "Closing query");
        mongoc_cursor_destroy(cursor->mcursor);
        free(cursor);
    }
}


text:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
coverage run --include=foldbeam/* ${DIR}/setup.py test; coverage html

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html>

		<meta charset="utf-8">
		<title>Justin Shih About</title>
		<link rel="stylesheet" href="style.css">

							Industrial Designer

Bachelor of Industrial Design (Honours)

Having taken electives in Web design, Built Environment Interdisplinary Design (BEIL) and Graphic design for the Built Environment; I am interested in all things design especially in the marriage between the 2D and the 3D

Through my projects I've always aimed to enrich the interactions between user and product with a heightened sense of fulfilment through form and user experience

Thoughtful, emotive design with emphasis on design semantics, ultimately designing projects that are fun and benefit the lives of the users in a meaningful way on all aspects

Interested areas: Bathroom design, furniture design. Internet of Things and integrated systems, Electronic design, Smart textiles and wearables

							Australian,
台湾人

Born in Taipei, Taiwan but soon moved to Sydney, Australia by a couple of months old

Grew up in Sydney and Gold Coast, Australia

							Unsw

Graduated in 2018 with a Bachelors of Industrial Design (Honours) from the University of New South Wales

							1995

Born 1995

Graduated high school 2013

Completed Undergraduate degree 2018

							English,
中文,
日本語

Having grown up in Australia with a Taiwanese background,

English is my first language with relative fluency in spoken Mandarin as well as an intermediate level of reading.

Basic understanding of conversational Cantonese

Basic understanding of conversational Japanese as well as basic writing and reading.

							Apple

As a Sales specialist and Technical specialist with experiences in Inventory and Visualisation in Apple Retail. I've acquired the opportunities to enhance my experiences and knowledge as a designer even by indirect and incremental quantities.

Having interacted with the store on a highly personal level my understanding of the industrial design, engineering and architecture that goes into an Apple retail store has been surprised. Everything from the seemingly minimal but highly multi-functional furniture, POS displays to the tiniest of fixtures, adhesions and the ultimate assembly of everything that is the retail store both to what is customer-facing and to what is behind-the-scenes on how the operations are run, designerly-speaking has been eye-opening.

							Accolades

2013 | Year 12 HSC Design & Technology - 1st Place

2015 | Caroma Ergonomics Award for Bathroom Design - Best Team Proposal


text:
package org.supercsv.ext.localization;

import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.support.MessageSourceAccessor;

/**
 * MessageResolver via Spring 'org.springframework.context.MessageSource'.
 *
 * @author T.TSUCHIE
 *
 */
public class SpringMessageResolver implements MessageResolver {

    protected MessageSourceAccessor messageSourceAccessor;

    public SpringMessageResolver() {

    }

    public SpringMessageResolver(final MessageSource messageSource) {
        setMessageSource(messageSource);
    }

    /**
     * {@inheritDoc}
     */
    public String getMessage(final String code) {
        try {
            return messageSourceAccessor.getMessage(code);
        } catch(NoSuchMessageException e) {
            return null;
        }
    }

    public void setMessageSource(final MessageSource messageSource) {
        this.messageSourceAccessor = new MessageSourceAccessor(messageSource);
    }

    protected MessageSourceAccessor getMessageSourceAccessor() {
        return messageSourceAccessor;
    }
}


text:
import {TestBed, ComponentFixture} from '@angular/core/testing';
import {createGenericTestComponent} from '../test/common';

import {Component} from '@angular/core';

import {NgbHighlight} from './highlight';
import {NgbTypeaheadModule} from './typeahead.module';

const createTestComponent = (html: string) =>
    createGenericTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;

/**
 * Get generated innerHtml without HTML comments and Angular debug attributes
 */
function highlightHtml(fixture) {
  const elms = fixture.nativeElement.children[0].childNodes;
  let elm;
  let result = '';
  let nodeName;

  for (let i = 0; i < elms.length; i++) {
    elm = elms[i];

    if (elm.nodeType === Node.ELEMENT_NODE) {
      nodeName = elm.nodeName.toLowerCase();
      result += `<${nodeName} class="${elm.className}">${elm.textContent}</${nodeName}>`;
    } else if (elm.nodeType === Node.TEXT_NODE) {
      result += elm.wholeText;
    }
  }

  return result;
}

describe('ngb-highlight', () => {

  beforeEach(() => {
    TestBed.overrideModule(NgbTypeaheadModule, {set: {exports: [NgbHighlight]}});
    TestBed.configureTestingModule({declarations: [TestComponent], imports: [NgbTypeaheadModule.forRoot()]})
        .compileComponents();
  });

  it('should render highlighted text when there is one match', () => {
    const fixture = createTestComponent('<ngb-highlight result="foo bar baz" term="bar"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe('foo bar baz');
  });

  it('should render highlighted text when there are multiple matches', () => {
    const fixture = createTestComponent('<ngb-highlight result="foo bar baz bar foo" term="bar"></ngb-highlight>');

    expect(highlightHtml(fixture))
        .toBe('foo bar baz bar foo');
  });

  it('should render highlighted text when there is a match at the beginning', () => {
    const fixture = createTestComponent('<ngb-highlight result="bar baz" term="bar"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe('bar baz');
  });

  it('should render highlighted text when there is a match at the end', () => {
    const fixture = createTestComponent('<ngb-highlight result="bar baz" term="baz"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe('bar baz');
  });

  it('should render highlighted text when there is a case-insensitive match', () => {
    const fixture = createTestComponent('<ngb-highlight result="foo bAR baz" term="bar"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe('foo bAR baz');
  });

  it('should render highlighted text with special characters', () => {
    const fixture = createTestComponent('<ngb-highlight result="foo (bAR baz" term="(BAR"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe('foo (bAR baz');
  });

  it('should render highlighted text for stringified non-string args', () => {
    const fixture = createTestComponent('<ngb-highlight [result]="123" term="2"></ngb-highlight>');
    fixture.detectChanges();
    expect(highlightHtml(fixture)).toBe('123');
  });

  it('should behave reasonably for blank result', () => {
    const fixture = createTestComponent('<ngb-highlight [result]="null" term="2"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe('');
  });

  it('should not convert null result to string', () => {
    const fixture = createTestComponent('<ngb-highlight [result]="null" term="null"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe('');
  });

  it('should properly detect matches in 0 result', () => {
    const fixture = createTestComponent('<ngb-highlight [result]="0" term="0"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe(`<span class="ngb-highlight">0</span>`);
  });

  it('should not higlight anything for blank term', () => {
    const fixture = createTestComponent('<ngb-highlight result="1null23" [term]="null"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe('1null23');
  });

  it('should not higlight anything for blank term', () => {
    const fixture = createTestComponent(`<ngb-highlight result="123" [term]="''"></ngb-highlight>`);

    expect(highlightHtml(fixture)).toBe('123');
  });

  it('should properly higlight zeros', () => {
    const fixture = createTestComponent(`<ngb-highlight result="0123" [term]="0"></ngb-highlight>`);

    expect(highlightHtml(fixture)).toBe('0123');
  });

  it('should support custom highlight class', () => {
    const fixture = createTestComponent('<ngb-highlight result="123" [term]="2" highlightClass="my"></ngb-highlight>');

    expect(highlightHtml(fixture)).toBe('123');
  });
});

@Component({selector: 'test-cmp', template: ''})
class TestComponent {
}


text:
import logging
from uuid import uuid4

from flask import current_app, request, jsonify, render_template
from flask_cors import cross_origin

from alerta.app.utils.api import absolute_url
from alerta.app.exceptions import ApiError, NoCustomerMatch
from alerta.app.models.user import User
from alerta.app.models.customer import Customer

from alerta.app.auth.utils import create_token

from . import auth

@auth.route('/auth/signup', methods=['OPTIONS', 'POST'])
@cross_origin(supports_credentials=True)
def signup():
    try:
        user = User.parse(request.json)
    except Exception as e:
        raise ApiError(str(e), 400)

    if User.get_by_email(user.email):
        raise ApiError("user already exists", 409)

    try:
        user = user.create()
    except Exception as e:
        ApiError(str(e), 500)

    # if email verification is enforced, deny login and send email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        hash = str(uuid4())
        send_confirmation(user, hash)
        user.set_email_hash(hash)
        raise ApiError('email not verified', 401)

    # check allowed domain
    if user.domain not in current_app.config['ALLOWED_EMAIL_DOMAINS'] and '*' not in current_app.config[
        'ALLOWED_EMAIL_DOMAINS']:
        raise ApiError("unauthorized domain", 403)

    # assign customer
    if current_app.config['CUSTOMER_VIEWS']:
        try:
            customer = Customer.lookup(user.email, groups=[user.domain])
        except NoCustomerMatch as e:
            raise ApiError(str(e), 403)
    else:
        customer = None

    user.update_last_login()

    # generate token
    token = create_token(user.id, user.name, user.email, provider='basic', customer=customer,
                         roles=[user.role], email=user.email, email_verified=user.email_verified)
    return jsonify(token=token.tokenize)

@auth.route('/auth/login', methods=['OPTIONS', 'POST'])
@cross_origin(supports_credentials=True)
def login():
    # lookup user from login/email
    try:
        email = request.json['email']
        password = request.json['password']
    except KeyError:
        raise ApiError("must supply 'email' and 'password'", 401)

    user = User.get_by_email(email)
    if not user:
        raise ApiError("invalid user", 401)

    if not user.verify_password(password):
        raise ApiError("invalid password", 401)

    if current_app.config['EMAIL_VERIFICATION'] and user.email_verified == False:
        # FIXME link for resend verification
        raise ApiError('email not verified', 401)

    # verify domain
    if user.domain not in current_app.config['ALLOWED_EMAIL_DOMAINS'] and '*' not in current_app.config['ALLOWED_EMAIL_DOMAINS']:
        raise ApiError("unauthorized domain", 403)

    # assign customer
    if current_app.config['CUSTOMER_VIEWS']:
        try:
            customer = Customer.lookup(user.email, groups=[user.domain])
        except NoCustomerMatch as e:
            raise ApiError(str(e), 403)
    else:
        customer = None

    user.update_last_login()

    # generate token
    token = create_token(user.id, user.name, user.email, provider='basic', customer=customer,
                         roles=[user.role], email=user.email, email_verified=user.email_verified)
    return jsonify(token=token.tokenize)

@auth.route('/auth/confirm/<hash>', methods=['GET'])
def verify_email(hash):

    user = User.verify_hash(hash)
    if not user.email_verified:
        user.set_email_verified()
        return render_template('auth/verify_success.html', email=user.email)
    else:
        return render_template('auth/verify_failed.html')

try:
    import smtplib
    import socket
    from email.mime.text import MIMEText
    from email.mime.multipart import MIMEMultipart
except ImportError:
    pass

def send_confirmation(user, hash):

    msg = MIMEMultipart('related')
    msg['Subject'] = "[Alerta] Please verify your email '%s'" % user.email
    msg['From'] = current_app.config['MAIL_FROM']
    msg['To'] = user.email
    msg.preamble = "[Alerta] Please verify your email '%s'" % user.email

    text = 'Hello {name}!\n\n' \
           'Please verify your email address is {email} by clicking on the link below:\n\n' \
           '{url}\n\n' \
           'You\'re receiving this email because you recently created a new Alerta account.' \
           ' If this wasn\'t you, please ignore this email.'.format(
               name=user.name, email=user.email, url=absolute_url('/auth/confirm/' + hash))

    msg_text = MIMEText(text, 'plain', 'utf-8')
    msg.attach(msg_text)

    try:
        mx = smtplib.SMTP(current_app.config['SMTP_HOST'], current_app.config['SMTP_PORT'])
        if current_app.config['DEBUG']:
            mx.set_debuglevel(True)
        mx.ehlo()
        mx.starttls()
        mx.login(current_app.config['MAIL_FROM'], current_app.config['SMTP_PASSWORD'])
        mx.sendmail(current_app.config['MAIL_FROM'], [user.email], msg.as_string())
        mx.close()
    except (socket.error, socket.herror, socket.gaierror) as e:
        logging.error('Mail server connection error: %s', str(e))
        return
    except smtplib.SMTPException as e:
        logging.error('Failed to send email : %s', str(e))
    except Exception as e:
        logging.error('Unhandled exception: %s', str(e))


text:
#include <gui/ControlWidget.h>

#include <QtDebug>

/*!
 * Constructor
 */
ControlWidget::ControlWidget(QWidget *ipParent)
    : QWidget(ipParent)
{
    ui.setupUi(this);

    setMinZoom(0);
    setMaxZoom(10);
    setZoom(5);
}

/*!
 * Destructor
 */
ControlWidget::~ControlWidget()
{
}

/*!
 * \brief Process value changed signal (just emit the signal)
 *
 * \param[in] ipFactor -
 */
void
ControlWidget::changeValue(int ipFactor)
{
    emit valueChanged(ipFactor);
}

/*!
 * \brief Increment value
 */
void
ControlWidget::increaseValue()
{
    ui.mScaleSlider->setValue(ui.mScaleSlider->value() + 1);
}

/*!
 * Decrement value
 */
void
ControlWidget::decreaseValue()
{
    ui.mScaleSlider->setValue(ui.mScaleSlider->value() - 1);
}

/*!
 * \brief Move the scene up
 */
void
ControlWidget::moveUp()
{
    emit movedUp();
}

/*!
 * \brief Move the scene down
 */
void
ControlWidget::moveDown()
{
    emit movedDown();
}

/*!
 * \brief Move the scene left
 */
void
ControlWidget::moveLeft()
{
    emit movedLeft();
}

/*!
 * \breif Move the scene right
 */
void
ControlWidget::moveRight()
{
    emit movedRight();
}

/*!
 * \brief Set move mode/drag&drop mode
 */
void
ControlWidget::setMoveMode()
{
    emit moveModeSet(ui.mMoveButton->isChecked());
}

/*!
 * \brief Get the minimum scaling factor
 *
 * \return Minimum scaling factor
 */
int
ControlWidget::minZoom() const
{
    return ui.mScaleSlider->minimum();
}

/*!
 * \brief Set the minimum scaling factor
 *
 * \param[in] ipVal - Minimum scaling factor
 */
void
ControlWidget::setMinZoom(int ipVal)
{
    ui.mScaleSlider->setMinimum(ipVal);
}

/*!
 * \brief Get the maximum scaling factor
 *
 * \return Maximum scaling factor
 */
int
ControlWidget::maxZoom() const
{
    return ui.mScaleSlider->maximum();
}

/*!
 * \brief Set the maximum scaling factor
 *
 * \param[in] ipVal - Maximum scaling factor
 */
void
ControlWidget::setMaxZoom(int ipVal)
{
    ui.mScaleSlider->setMaximum(ipVal);
}

/*!
 * \brief Get current scaling factor
 *
 * \return Current scaling factor
 */
int
ControlWidget::zoom() const
{
    return ui.mScaleSlider->value();
}

/*!
 * \brief Set current scaling factor
 *
 * \param[in] ipVal - Current scaling factor
 */
void
ControlWidget::setZoom(int ipVal)
{
    ui.mScaleSlider->setValue(ipVal);
}


text:
package org.nutz.weixin.bean;

/**
 * 微信支付统一下单
 * Created by wizzer on 2017/3/23.
 */
public class WxPayUnifiedOrder {
    private String appid;
    private String mch_id;
    private String sub_appid;
    private String sub_mch_id;
    private String device_info;
    private String nonce_str;
    private String sign;
    private String sign_type;
    private String body;
    private String detail;
    private String attach;
    private String out_trade_no;
    private String fee_type;
    private int total_fee;
    private String spbill_create_ip;
    private String time_start;
    private String time_expire;
    private String goods_tag;
    private String notify_url;
    private String trade_type;
    private String product_id;
    private String limit_pay;
    private String openid;

    public String getAppid() {
        return appid;
    }

    public void setAppid(String appid) {
        this.appid = appid;
    }

    public String getMch_id() {
        return mch_id;
    }

    public void setMch_id(String mch_id) {
        this.mch_id = mch_id;
    }

    public String getDevice_info() {
        return device_info;
    }

    public void setDevice_info(String device_info) {
        this.device_info = device_info;
    }

    public String getNonce_str() {
        return nonce_str;
    }

    public void setNonce_str(String nonce_str) {
        this.nonce_str = nonce_str;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getSign_type() {
        return sign_type;
    }

    public void setSign_type(String sign_type) {
        this.sign_type = sign_type;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public String getAttach() {
        return attach;
    }

    public void setAttach(String attach) {
        this.attach = attach;
    }

    public String getOut_trade_no() {
        return out_trade_no;
    }

    public void setOut_trade_no(String out_trade_no) {
        this.out_trade_no = out_trade_no;
    }

    public String getFee_type() {
        return fee_type;
    }

    public void setFee_type(String fee_type) {
        this.fee_type = fee_type;
    }

    public int getTotal_fee() {
        return total_fee;
    }

    public void setTotal_fee(int total_fee) {
        this.total_fee = total_fee;
    }

    public String getSpbill_create_ip() {
        return spbill_create_ip;
    }

    public void setSpbill_create_ip(String spbill_create_ip) {
        this.spbill_create_ip = spbill_create_ip;
    }

    public String getTime_start() {
        return time_start;
    }

    public void setTime_start(String time_start) {
        this.time_start = time_start;
    }

    public String getTime_expire() {
        return time_expire;
    }

    public void setTime_expire(String time_expire) {
        this.time_expire = time_expire;
    }

    public String getGoods_tag() {
        return goods_tag;
    }

    public void setGoods_tag(String goods_tag) {
        this.goods_tag = goods_tag;
    }

    public String getNotify_url() {
        return notify_url;
    }

    public void setNotify_url(String notify_url) {
        this.notify_url = notify_url;
    }

    public String getTrade_type() {
        return trade_type;
    }

    public void setTrade_type(String trade_type) {
        this.trade_type = trade_type;
    }

    public String getProduct_id() {
        return product_id;
    }

    public void setProduct_id(String product_id) {
        this.product_id = product_id;
    }

    public String getLimit_pay() {
        return limit_pay;
    }

    public void setLimit_pay(String limit_pay) {
        this.limit_pay = limit_pay;
    }

    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }

    public String getSub_appid() {
        return sub_appid;
    }

    public void setSub_appid(String sub_appid) {
        this.sub_appid = sub_appid;
    }

    public String getSub_mch_id() {
        return sub_mch_id;
    }

    public void setSub_mch_id(String sub_mch_id) {
        this.sub_mch_id = sub_mch_id;
    }
}


text:
/* eslint-disable */
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
var packageConfig = require('./package.json').config;
var ip = require('ip');
var argv = require('yargs')
    .default('p', packageConfig.PORT || 8000)
    .default('a', packageConfig.DB_PORT || 8001)
    .default('d', packageConfig.DELAY || 500)
    .argv;
var jsonServer = require('json-server');

/* re-implementation of connect-pause for handling delay of 0 */
var pause = function(delay, err) {
    delay = delay || 0; // original is 1000

    return function(req, res, next) {
        setTimeout(next, delay, err);
    };
};

var PORT = argv.p;
var DB_PORT = argv.a;
var DELAY = argv.d;

new WebpackDevServer(webpack(config), {
  publicPath: config.output.publicPath,
  hot: true,
  noInfo: true,
  historyApiFallback: true,
}).listen(PORT, '0.0.0.0', function (err, result) {
  if (err) {
    return console.log(err);
  }

  console.log(`Server started at http://localhost:${PORT}/`);
  console.log(`Tunnel started at http://${ip.address()}:${PORT}/`);

  jsonServer.create()
      .use(jsonServer.defaults())
      .use(pause(DELAY))
      .use(jsonServer.router('db.json'))
      .listen(DB_PORT, function(err) {
          if (err) {
              return console.log(err);
          }

          console.log(`Fake api server opened at port ${DB_PORT}`);
      })
});


text:
package org.elasticsearch.common.logging.log4j;

import org.apache.log4j.Layout;
import org.apache.log4j.WriterAppender;
import org.apache.log4j.helpers.LogLog;
import org.elasticsearch.common.logging.Loggers;

import java.io.IOException;
import java.io.OutputStream;

/**
 * ConsoleAppender appends log events to System.out or
 * System.err using a layout specified by the user. The
 * default target is System.out.
 *

 *
ElasticSearch: Adapter from log4j to allow to disable console logging...

 *
 * @author Ceki Gülcü
 * @author Curt Arnold
 * @since 1.1
 */
public class ConsoleAppender extends WriterAppender {

    public static final String SYSTEM_OUT = "System.out";
    public static final String SYSTEM_ERR = "System.err";

    protected String target = SYSTEM_OUT;

    /**
     * Determines if the appender honors reassignments of System.out
     * or System.err made after configuration.
     */
    private boolean follow = true;

    /**
     * Constructs an unconfigured appender.
     */
    public ConsoleAppender() {
    }

    /**
     * Creates a configured appender.
     *
     * @param layout layout, may not be null.
     */
    public ConsoleAppender(Layout layout) {
        this(layout, SYSTEM_OUT);
    }

    /**
     * Creates a configured appender.
     *
     * @param layout layout, may not be null.
     * @param target target, either "System.err" or "System.out".
     */
    public ConsoleAppender(Layout layout, String target) {
        setLayout(layout);
        setTarget(target);
        activateOptions();
    }

    /**
     * Sets the value of the Target option. Recognized values
     * are "System.out" and "System.err". Any other value will be
     * ignored.
     */
    public void setTarget(String value) {
        String v = value.trim();

        if (SYSTEM_OUT.equalsIgnoreCase(v)) {
            target = SYSTEM_OUT;
        } else if (SYSTEM_ERR.equalsIgnoreCase(v)) {
            target = SYSTEM_ERR;
        } else {
            targetWarn(value);
        }
    }

    /**
     * Returns the current value of the Target property. The
     * default value of the option is "System.out".
     *

     * See also {@link #setTarget}.
     */
    public String getTarget() {
        return target;
    }

    /**
     * Sets whether the appender honors reassignments of System.out
     * or System.err made after configuration.
     *
     * @param newValue if true, appender will use value of System.out or
     *                 System.err in force at the time when logging events are appended.
     * @since 1.2.13
     */
    public final void setFollow(final boolean newValue) {
        follow = newValue;
    }

    /**
     * Gets whether the appender honors reassignments of System.out
     * or System.err made after configuration.
     *
     * @return true if appender will use value of System.out or
     *         System.err in force at the time when logging events are appended.
     * @since 1.2.13
     */
    public final boolean getFollow() {
        return follow;
    }

    void targetWarn(String val) {
        LogLog.warn("[" + val + "] should be System.out or System.err.");
        LogLog.warn("Using previously set target, System.out by default.");
    }

    /**
     * Prepares the appender for use.
     */
    public void activateOptions() {
        if (follow) {
            if (target.equals(SYSTEM_ERR)) {
                setWriter(createWriter(new SystemErrStream()));
            } else {
                setWriter(createWriter(new SystemOutStream()));
            }
        } else {
            if (target.equals(SYSTEM_ERR)) {
                setWriter(createWriter(System.err));
            } else {
                setWriter(createWriter(System.out));
            }
        }

        super.activateOptions();
    }

    /**
     * {@inheritDoc}
     */
    protected
    final void closeWriter() {
        if (follow) {
            super.closeWriter();
        }
    }

    /**
     * An implementation of OutputStream that redirects to the
     * current System.err.
     */
    private static class SystemErrStream extends OutputStream {
        public SystemErrStream() {
        }

        public void close() {
        }

        public void flush() {
            System.err.flush();
        }

        public void write(final byte[] b) throws IOException {
            if (!Loggers.consoleLoggingEnabled()) {
                return;
            }
            System.err.write(b);
        }

        public void write(final byte[] b, final int off, final int len)
                throws IOException {
            if (!Loggers.consoleLoggingEnabled()) {
                return;
            }
            System.err.write(b, off, len);
        }

        public void write(final int b) throws IOException {
            if (!Loggers.consoleLoggingEnabled()) {
                return;
            }
            System.err.write(b);
        }
    }

    /**
     * An implementation of OutputStream that redirects to the
     * current System.out.
     */
    private static class SystemOutStream extends OutputStream {
        public SystemOutStream() {
        }

        public void close() {
        }

        public void flush() {
            System.out.flush();
        }

        public void write(final byte[] b) throws IOException {
            if (!Loggers.consoleLoggingEnabled()) {
                return;
            }
            System.out.write(b);
        }

        public void write(final byte[] b, final int off, final int len)
                throws IOException {
            if (!Loggers.consoleLoggingEnabled()) {
                return;
            }
            System.out.write(b, off, len);
        }

        public void write(final int b) throws IOException {
            if (!Loggers.consoleLoggingEnabled()) {
                return;
            }
            System.out.write(b);
        }
    }

}


text:
require "spec_helper"

describe Module do
  class TestClass
    lazy_attribute(:without_block)
    lazy_attribute(:test){"Test"}

    lazy_attribute(:public_attr, :public) {"Test"}
    lazy_attribute(:protected_attr, :protected) {"Test"}
    lazy_attribute(:private_attr, :private) {"Test"}
  end

  let(:test) {TestClass.new}

  it "is nil without code block" do
    expect(test.without_block).to be_nil
  end

  it "returns value of the code block" do
    expect(test.test).to eq "Test"
  end

  it "supports assignment" do
    expected = "This is a test"
    test.test = expected
    expect(test.test).to eq expected
  end

  context "default visibility" do
    it "defines public reader" do
      expect(test.public_methods.map(&:to_s)).to include("test")
    end

    it "defines public writer" do
      expect(test.public_methods.map(&:to_s)).to include("test=")
    end
  end

  context "public visibility" do
    it "defines public reader" do
      expect(test.public_methods.map(&:to_s)).to include("public_attr")
    end

    it "defines public writer" do
      expect(test.public_methods.map(&:to_s)).to include("public_attr=")
    end
  end

  context "protected visibility" do
    it "defines protected reader" do
      expect(test.protected_methods.map(&:to_s)).to include("protected_attr")
    end

    it "defines protected writer" do
      expect(test.protected_methods.map(&:to_s)).to include("protected_attr=")
    end
  end

  context "private visibility" do
    it "defines private reader" do
      expect(test.private_methods.map(&:to_s)).to include("private_attr")
    end

    it "defines private writer" do
      expect(test.private_methods.map(&:to_s)).to include("private_attr=")
    end
  end
end


text:
redirect_to: https://www.axiomq.com/blog/display-part-of-rails-template-with-different-locale/
layout: post
title: "Show part of a Rails template in other locale"
date: 2016-05-30 10:06:00 +0200
comments: true
author: Ivica Lakatoš
categories:
  - Ruby and Rails
tags:
  - ruby
  - rails
  - I18n.locale
published: true
---

I recently worked on a Rails project, which had parts of pages in different languages. That may be a problem if you have already translated their entire text to all required languages. You can even be tempted to hardcode parts of the text into other languages. Fortunately, there is an elegant way to solve that problem, just wrap parts of template or partials into blocks with desired locale, like this:

``` ruby
<% I18n.with_locale('en') do %>
  ...part of your template
  or
  <%= render partial: 'some/partial' %>
<% end %>
```

### Example

Suppose, there is a template with only header and two paragraphs.

```
<h1><%= t('my_great_header') %></h1>

<p><%= t('first_paragraph') %></p>

<p><%= t('second_paragraph') %></p>
```
And locale in English and French for that template.

```
# in config/locales/en.yml
en:
  my_great_header: "My English great header"
  first_paragraph: "First English paragraph"
  second_paragraph: "Second English paragraph"

# in config/locales/fr.yml
fr:
  my_great_header: "My French great header"
  first_paragraph: "First French paragraph"
  second_paragraph: "Second French paragraph"
```

<!--more-->

And client wants first paragraph to always be in English.

Just wrap first paragraph in block with locale `'en`, like this:

```
<h1><%= t('my_great_header') %></h1>

<% I18n.with_locale('en') do %>
  <p><%= t('first_paragraph') %></p>
<% end %>
<p><%= t('second_paragraph') %></p>
```
and when you switch language to Franch result will be:

``` text
My French great header

First English paragraph

Second French paragraph
```

I hope that this helps. Have a nice day.


text:
"""Support for monitoring the local system."""
from __future__ import annotations

import asyncio
from dataclasses import dataclass
from datetime import datetime, timedelta
from functools import lru_cache
import logging
import os
import socket
import sys
from typing import Any, cast

import psutil
import voluptuous as vol

from homeassistant.components.sensor import (
    PLATFORM_SCHEMA,
    SensorDeviceClass,
    SensorEntity,
    SensorEntityDescription,
    SensorStateClass,
)
from homeassistant.const import (
    CONF_RESOURCES,
    CONF_SCAN_INTERVAL,
    CONF_TYPE,
    DATA_GIBIBYTES,
    DATA_MEBIBYTES,
    DATA_RATE_MEGABYTES_PER_SECOND,
    EVENT_HOMEASSISTANT_STOP,
    PERCENTAGE,
    STATE_OFF,
    STATE_ON,
    TEMP_CELSIUS,
)
from homeassistant.core import HomeAssistant, callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import (
    async_dispatcher_connect,
    async_dispatcher_send,
)
from homeassistant.helpers.entity_component import DEFAULT_SCAN_INTERVAL
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.typing import ConfigType
from homeassistant.util import slugify
import homeassistant.util.dt as dt_util

_LOGGER = logging.getLogger(__name__)

CONF_ARG = "arg"

if sys.maxsize > 2 ** 32:
    CPU_ICON = "mdi:cpu-64-bit"
else:
    CPU_ICON = "mdi:cpu-32-bit"

SENSOR_TYPE_NAME = 0
SENSOR_TYPE_UOM = 1
SENSOR_TYPE_ICON = 2
SENSOR_TYPE_DEVICE_CLASS = 3
SENSOR_TYPE_MANDATORY_ARG = 4

SIGNAL_SYSTEMMONITOR_UPDATE = "systemmonitor_update"

@dataclass
class SysMonitorSensorEntityDescription(SensorEntityDescription):
    """Description for System Monitor sensor entities."""

    mandatory_arg: bool = False

SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription] = {
    "disk_free": SysMonitorSensorEntityDescription(
        key="disk_free",
        name="Disk free",
        native_unit_of_measurement=DATA_GIBIBYTES,
        icon="mdi:harddisk",
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "disk_use": SysMonitorSensorEntityDescription(
        key="disk_use",
        name="Disk use",
        native_unit_of_measurement=DATA_GIBIBYTES,
        icon="mdi:harddisk",
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "disk_use_percent": SysMonitorSensorEntityDescription(
        key="disk_use_percent",
        name="Disk use (percent)",
        native_unit_of_measurement=PERCENTAGE,
        icon="mdi:harddisk",
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "ipv4_address": SysMonitorSensorEntityDescription(
        key="ipv4_address",
        name="IPv4 address",
        icon="mdi:server-network",
        mandatory_arg=True,
    ),
    "ipv6_address": SysMonitorSensorEntityDescription(
        key="ipv6_address",
        name="IPv6 address",
        icon="mdi:server-network",
        mandatory_arg=True,
    ),
    "last_boot": SysMonitorSensorEntityDescription(
        key="last_boot",
        name="Last boot",
        device_class=SensorDeviceClass.TIMESTAMP,
    ),
    "load_15m": SysMonitorSensorEntityDescription(
        key="load_15m",
        name="Load (15m)",
        icon=CPU_ICON,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "load_1m": SysMonitorSensorEntityDescription(
        key="load_1m",
        name="Load (1m)",
        icon=CPU_ICON,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "load_5m": SysMonitorSensorEntityDescription(
        key="load_5m",
        name="Load (5m)",
        icon=CPU_ICON,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "memory_free": SysMonitorSensorEntityDescription(
        key="memory_free",
        name="Memory free",
        native_unit_of_measurement=DATA_MEBIBYTES,
        icon="mdi:memory",
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "memory_use": SysMonitorSensorEntityDescription(
        key="memory_use",
        name="Memory use",
        native_unit_of_measurement=DATA_MEBIBYTES,
        icon="mdi:memory",
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "memory_use_percent": SysMonitorSensorEntityDescription(
        key="memory_use_percent",
        name="Memory use (percent)",
        native_unit_of_measurement=PERCENTAGE,
        icon="mdi:memory",
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "network_in": SysMonitorSensorEntityDescription(
        key="network_in",
        name="Network in",
        native_unit_of_measurement=DATA_MEBIBYTES,
        icon="mdi:server-network",
        state_class=SensorStateClass.TOTAL_INCREASING,
        mandatory_arg=True,
    ),
    "network_out": SysMonitorSensorEntityDescription(
        key="network_out",
        name="Network out",
        native_unit_of_measurement=DATA_MEBIBYTES,
        icon="mdi:server-network",
        state_class=SensorStateClass.TOTAL_INCREASING,
        mandatory_arg=True,
    ),
    "packets_in": SysMonitorSensorEntityDescription(
        key="packets_in",
        name="Packets in",
        icon="mdi:server-network",
        state_class=SensorStateClass.TOTAL_INCREASING,
        mandatory_arg=True,
    ),
    "packets_out": SysMonitorSensorEntityDescription(
        key="packets_out",
        name="Packets out",
        icon="mdi:server-network",
        state_class=SensorStateClass.TOTAL_INCREASING,
        mandatory_arg=True,
    ),
    "throughput_network_in": SysMonitorSensorEntityDescription(
        key="throughput_network_in",
        name="Network throughput in",
        native_unit_of_measurement=DATA_RATE_MEGABYTES_PER_SECOND,
        icon="mdi:server-network",
        state_class=SensorStateClass.MEASUREMENT,
        mandatory_arg=True,
    ),
    "throughput_network_out": SysMonitorSensorEntityDescription(
        key="throughput_network_out",
        name="Network throughput out",
        native_unit_of_measurement=DATA_RATE_MEGABYTES_PER_SECOND,
        icon="mdi:server-network",
        state_class=SensorStateClass.MEASUREMENT,
        mandatory_arg=True,
    ),
    "process": SysMonitorSensorEntityDescription(
        key="process",
        name="Process",
        icon=CPU_ICON,
        state_class=SensorStateClass.MEASUREMENT,
        mandatory_arg=True,
    ),
    "processor_use": SysMonitorSensorEntityDescription(
        key="processor_use",
        name="Processor use",
        native_unit_of_measurement=PERCENTAGE,
        icon=CPU_ICON,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "processor_temperature": SysMonitorSensorEntityDescription(
        key="processor_temperature",
        name="Processor temperature",
        native_unit_of_measurement=TEMP_CELSIUS,
        device_class=SensorDeviceClass.TEMPERATURE,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "swap_free": SysMonitorSensorEntityDescription(
        key="swap_free",
        name="Swap free",
        native_unit_of_measurement=DATA_MEBIBYTES,
        icon="mdi:harddisk",
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "swap_use": SysMonitorSensorEntityDescription(
        key="swap_use",
        name="Swap use",
        native_unit_of_measurement=DATA_MEBIBYTES,
        icon="mdi:harddisk",
        state_class=SensorStateClass.MEASUREMENT,
    ),
    "swap_use_percent": SysMonitorSensorEntityDescription(
        key="swap_use_percent",
        name="Swap use (percent)",
        native_unit_of_measurement=PERCENTAGE,
        icon="mdi:harddisk",
        state_class=SensorStateClass.MEASUREMENT,
    ),
}

def check_required_arg(value: Any) -> Any:
    """Validate that the required "arg" for the sensor types that need it are set."""
    for sensor in value:
        sensor_type = sensor[CONF_TYPE]
        sensor_arg = sensor.get(CONF_ARG)

        if sensor_arg is None and SENSOR_TYPES[sensor_type].mandatory_arg:
            raise vol.RequiredFieldInvalid(
                f"Mandatory 'arg' is missing for sensor type '{sensor_type}'."
            )

    return value

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
    {
        vol.Optional(CONF_RESOURCES, default={CONF_TYPE: "disk_use"}): vol.All(
            cv.ensure_list,
            [
                vol.Schema(
                    {
                        vol.Required(CONF_TYPE): vol.In(SENSOR_TYPES),
                        vol.Optional(CONF_ARG): cv.string,
                    }
                )
            ],
            check_required_arg,
        )
    }
)

IO_COUNTER = {
    "network_out": 0,
    "network_in": 1,
    "packets_out": 2,
    "packets_in": 3,
    "throughput_network_out": 0,
    "throughput_network_in": 1,
}

IF_ADDRS_FAMILY = {"ipv4_address": socket.AF_INET, "ipv6_address": socket.AF_INET6}

# There might be additional keys to be added for different
# platforms / hardware combinations.
# Taken from last version of "glances" integration before they moved to
# a generic temperature sensor logic.
# https://github.com/home-assistant/core/blob/5e15675593ba94a2c11f9f929cdad317e27ce190/homeassistant/components/glances/sensor.py#L199
CPU_SENSOR_PREFIXES = [
    "amdgpu 1",
    "aml_thermal",
    "Core 0",
    "Core 1",
    "CPU Temperature",
    "CPU",
    "cpu-thermal 1",
    "cpu_thermal 1",
    "exynos-therm 1",
    "Package id 0",
    "Physical id 0",
    "radeon 1",
    "soc-thermal 1",
    "soc_thermal 1",
    "Tctl",
    "cpu0-thermal",
]

@dataclass
class SensorData:
    """Data for a sensor."""

    argument: Any
    state: str | datetime | None
    value: Any | None
    update_time: datetime | None
    last_exception: BaseException | None

async def async_setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: Any | None = None,
) -> None:
    """Set up the system monitor sensors."""
    entities = []
    sensor_registry: dict[tuple[str, str], SensorData] = {}

    for resource in config[CONF_RESOURCES]:
        type_ = resource[CONF_TYPE]
        # Initialize the sensor argument if none was provided.
        # For disk monitoring default to "/" (root) to prevent runtime errors, if argument was not specified.
        if CONF_ARG not in resource:
            argument = ""
            if resource[CONF_TYPE].startswith("disk_"):
                argument = "/"
        else:
            argument = resource[CONF_ARG]

        # Verify if we can retrieve CPU / processor temperatures.
        # If not, do not create the entity and add a warning to the log
        if (
            type_ == "processor_temperature"
            and await hass.async_add_executor_job(_read_cpu_temperature) is None
        ):
            _LOGGER.warning("Cannot read CPU / processor temperature information")
            continue

        sensor_registry[(type_, argument)] = SensorData(
            argument, None, None, None, None
        )
        entities.append(
            SystemMonitorSensor(sensor_registry, SENSOR_TYPES[type_], argument)
        )

    scan_interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
    await async_setup_sensor_registry_updates(hass, sensor_registry, scan_interval)

    async_add_entities(entities)

async def async_setup_sensor_registry_updates(
    hass: HomeAssistant,
    sensor_registry: dict[tuple[str, str], SensorData],
    scan_interval: timedelta,
) -> None:
    """Update the registry and create polling."""

    _update_lock = asyncio.Lock()

    def _update_sensors() -> None:
        """Update sensors and store the result in the registry."""
        for (type_, argument), data in sensor_registry.items():
            try:
                state, value, update_time = _update(type_, data)
            except Exception as ex:  # pylint: disable=broad-except
                _LOGGER.exception("Error updating sensor: %s (%s)", type_, argument)
                data.last_exception = ex
            else:
                data.state = state
                data.value = value
                data.update_time = update_time
                data.last_exception = None

        # Only fetch these once per iteration as we use the same
        # data source multiple times in _update
        _disk_usage.cache_clear()
        _swap_memory.cache_clear()
        _virtual_memory.cache_clear()
        _net_io_counters.cache_clear()
        _net_if_addrs.cache_clear()
        _getloadavg.cache_clear()

    async def _async_update_data(*_: Any) -> None:
        """Update all sensors in one executor jump."""
        if _update_lock.locked():
            _LOGGER.warning(
                "Updating systemmonitor took longer than the scheduled update interval %s",
                scan_interval,
            )
            return

        async with _update_lock:
            await hass.async_add_executor_job(_update_sensors)
            async_dispatcher_send(hass, SIGNAL_SYSTEMMONITOR_UPDATE)

    polling_remover = async_track_time_interval(hass, _async_update_data, scan_interval)

    @callback
    def _async_stop_polling(*_: Any) -> None:
        polling_remover()

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _async_stop_polling)

    await _async_update_data()

class SystemMonitorSensor(SensorEntity):
    """Implementation of a system monitor sensor."""

    should_poll = False

    def __init__(
        self,
        sensor_registry: dict[tuple[str, str], SensorData],
        sensor_description: SysMonitorSensorEntityDescription,
        argument: str = "",
    ) -> None:
        """Initialize the sensor."""
        self.entity_description = sensor_description
        self._attr_name: str = f"{sensor_description.name} {argument}".rstrip()
        self._attr_unique_id: str = slugify(f"{sensor_description.key}_{argument}")
        self._sensor_registry = sensor_registry
        self._argument: str = argument

    @property
    def native_value(self) -> str | datetime | None:
        """Return the state of the device."""
        return self.data.state

    @property
    def available(self) -> bool:
        """Return True if entity is available."""
        return self.data.last_exception is None

    @property
    def data(self) -> SensorData:
        """Return registry entry for the data."""
        return self._sensor_registry[(self.entity_description.key, self._argument)]

    async def async_added_to_hass(self) -> None:
        """When entity is added to hass."""
        await super().async_added_to_hass()
        self.async_on_remove(
            async_dispatcher_connect(
                self.hass, SIGNAL_SYSTEMMONITOR_UPDATE, self.async_write_ha_state
            )
        )

def _update(  # noqa: C901
    type_: str, data: SensorData
) -> tuple[str | datetime | None, str | None, datetime | None]:
    """Get the latest system information."""
    state = None
    value = None
    update_time = None

    if type_ == "disk_use_percent":
        state = _disk_usage(data.argument).percent
    elif type_ == "disk_use":
        state = round(_disk_usage(data.argument).used / 1024 ** 3, 1)
    elif type_ == "disk_free":
        state = round(_disk_usage(data.argument).free / 1024 ** 3, 1)
    elif type_ == "memory_use_percent":
        state = _virtual_memory().percent
    elif type_ == "memory_use":
        virtual_memory = _virtual_memory()
        state = round((virtual_memory.total - virtual_memory.available) / 1024 ** 2, 1)
    elif type_ == "memory_free":
        state = round(_virtual_memory().available / 1024 ** 2, 1)
    elif type_ == "swap_use_percent":
        state = _swap_memory().percent
    elif type_ == "swap_use":
        state = round(_swap_memory().used / 1024 ** 2, 1)
    elif type_ == "swap_free":
        state = round(_swap_memory().free / 1024 ** 2, 1)
    elif type_ == "processor_use":
        state = round(psutil.cpu_percent(interval=None))
    elif type_ == "processor_temperature":
        state = _read_cpu_temperature()
    elif type_ == "process":
        state = STATE_OFF
        for proc in psutil.process_iter():
            try:
                if data.argument == proc.name():
                    state = STATE_ON
                    break
            except psutil.NoSuchProcess as err:
                _LOGGER.warning(
                    "Failed to load process with ID: %s, old name: %s",
                    err.pid,
                    err.name,
                )
    elif type_ in ("network_out", "network_in"):
        counters = _net_io_counters()
        if data.argument in counters:
            counter = counters[data.argument][IO_COUNTER[type_]]
            state = round(counter / 1024 ** 2, 1)
        else:
            state = None
    elif type_ in ("packets_out", "packets_in"):
        counters = _net_io_counters()
        if data.argument in counters:
            state = counters[data.argument][IO_COUNTER[type_]]
        else:
            state = None
    elif type_ in ("throughput_network_out", "throughput_network_in"):
        counters = _net_io_counters()
        if data.argument in counters:
            counter = counters[data.argument][IO_COUNTER[type_]]
            now = dt_util.utcnow()
            if data.value and data.value < counter:
                state = round(
                    (counter - data.value)
                    / 1000 ** 2
                    / (now - (data.update_time or now)).total_seconds(),
                    3,
                )
            else:
                state = None
            update_time = now
            value = counter
        else:
            state = None
    elif type_ in ("ipv4_address", "ipv6_address"):
        addresses = _net_if_addrs()
        if data.argument in addresses:
            for addr in addresses[data.argument]:
                if addr.family == IF_ADDRS_FAMILY[type_]:
                    state = addr.address
        else:
            state = None
    elif type_ == "last_boot":
        # Only update on initial setup
        if data.state is None:
            state = dt_util.utc_from_timestamp(psutil.boot_time())
        else:
            state = data.state
    elif type_ == "load_1m":
        state = round(_getloadavg()[0], 2)
    elif type_ == "load_5m":
        state = round(_getloadavg()[1], 2)
    elif type_ == "load_15m":
        state = round(_getloadavg()[2], 2)

    return state, value, update_time

# When we drop python 3.8 support these can be switched to
# @cache https://docs.python.org/3.9/library/functools.html#functools.cache
@lru_cache(maxsize=None)
def _disk_usage(path: str) -> Any:
    return psutil.disk_usage(path)

@lru_cache(maxsize=None)
def _swap_memory() -> Any:
    return psutil.swap_memory()

@lru_cache(maxsize=None)
def _virtual_memory() -> Any:
    return psutil.virtual_memory()

@lru_cache(maxsize=None)
def _net_io_counters() -> Any:
    return psutil.net_io_counters(pernic=True)

@lru_cache(maxsize=None)
def _net_if_addrs() -> Any:
    return psutil.net_if_addrs()

@lru_cache(maxsize=None)
def _getloadavg() -> tuple[float, float, float]:
    return os.getloadavg()

def _read_cpu_temperature() -> float | None:
    """Attempt to read CPU / processor temperature."""
    temps = psutil.sensors_temperatures()

    for name, entries in temps.items():
        for i, entry in enumerate(entries, start=1):
            # In case the label is empty (e.g. on Raspberry PI 4),
            # construct it ourself here based on the sensor key name.
            _label = f"{name} {i}" if not entry.label else entry.label
            # check both name and label because some systems embed cpu# in the
            # name, which makes label not match because label adds cpu# at end.
            if _label in CPU_SENSOR_PREFIXES or name in CPU_SENSOR_PREFIXES:
                return cast(float, round(entry.current, 1))

    return None


text:
/**
 * Module dependencies
 */

var deploy = require('deploy-yml');
var superagent = require('superagent');
var fs = require('fs');
var exists = fs.exists;
var read = fs.readFile;
var parse = require('url').parse;
var format = require('url').format;

var PROPERTIES = [
  'buildpacks',
  'resources',
  'collaborators',
  'drain',
  'regions',
  'labs',
  'env',
  'app',
  'domains',
  'errorPage',
  'mount',
  'shortName'
];

module.exports = function(opts) {
  opts = opts || {};
  opts.name = opts.name || '.deploy';

  return function(task, fn) {
    var dir = task.dir;
    if (!dir) return fn();

    var path = dir + '/' + opts.name;
    exists(path, function(e) {
      if (!e) return fn();

      deploy(path)
        .use(resolveFs)
        .use(resolveGithub(opts))
        .fetch(PROPERTIES, function(err, props) {
          if (err) return fn(err);
          zip(task.info, props);
          fn();
        });
    });
  };
};

function zip(info, props) {
  PROPERTIES.forEach(function(prop, i) {
    info[prop] = props[i];
  });
}

function resolveFs(path, fn) {
  read(path, 'utf8', fn);
}

function resolveGithub(opts) {
  var token = opts.githubToken || process.env.GITHUB_TOKEN;
  return function(path, parent, fn) {
    var obj = parse(path);
    if (obj.hostname !== 'github.com') return fn('pass');
    obj.host = obj.hostname = 'api.github.com';
    var parts = obj.pathname.split('/');
    parts.splice(3, 0, 'contents')
    parts.splice(1, 0, 'repos');
    obj.pathname = parts.join('/');
    var url = format(obj);

    superagent
      .get(url)
      .auth(token, 'x-oauth-basic')
      .buffer(true)
      .set('accept', 'application/vnd.github.v3.raw')
      .end(function(err, res) {
        if (err) return fn(err);
        if (res.error) return fn(res.error);
        fn(null, res.text);
      });
  };
}


text:
        Have a tip or rumor to share? Just click on the icon and if you get a BrowserWatch net.fame be sure and display the icon on your own home page for all to see!

         foo


text:
'use strict';
module.exports = typeof setImmediate === 'function' ? setImmediate :
	function setImmediate(fn) { setTimeout(fn, 0); };