text:
#include <fcntl.h>
#include <mongoc.h>

#include "mongoc-client-private.h"
#include "mongoc-cursor-private.h"
#include "mongoc-uri-private.h"
#include "mongoc-util-private.h"

#include "TestSuite.h"
#include "test-conveniences.h"
#include "test-libmongoc.h"
#include "mock_server/future.h"
#include "mock_server/future-functions.h"
#include "mock_server/mock-server.h"

#undef MONGOC_LOG_DOMAIN
#define MONGOC_LOG_DOMAIN "exhaust-test"

int
skip_if_mongos (void)
{
   if (!TestSuite_CheckLive ()) {
      return 0;
   }
   return test_framework_is_mongos () ? 0 : 1;
}

static int64_t
get_timestamp (mongoc_client_t *client, mongoc_cursor_t *cursor)
{
   uint32_t server_id;

   server_id = mongoc_cursor_get_hint (cursor);

   if (client->topology->single_threaded) {
      mongoc_topology_scanner_node_t *scanner_node;

      scanner_node = mongoc_topology_scanner_get_node (
         client->topology->scanner, server_id);

      return scanner_node->timestamp;
   } else {
      mongoc_cluster_node_t *cluster_node;

      cluster_node = (mongoc_cluster_node_t *) mongoc_set_get (
         client->cluster.nodes, server_id);

      return cluster_node->timestamp;
   }
}

static void
test_exhaust_cursor (bool pooled)
{
   mongoc_stream_t *stream;
   mongoc_write_concern_t *wr;
   mongoc_client_t *client;
   mongoc_client_pool_t *pool = NULL;
   mongoc_collection_t *collection;
   mongoc_cursor_t *cursor;
   mongoc_cursor_t *cursor2;
   const bson_t *doc;
   bson_t q;
   bson_t b[10];
   bson_t *bptr[10];
   int i;
   bool r;
   uint32_t server_id;
   bson_error_t error;
   bson_oid_t oid;
   int64_t timestamp1;

   if (pooled) {
      pool = test_framework_client_pool_new ();
      client = mongoc_client_pool_pop (pool);
   } else {
      client = test_framework_client_new ();
   }
   assert (client);

   collection = get_test_collection (client, "test_exhaust_cursor");
   assert (collection);

   mongoc_collection_drop (collection, &error);

   wr = mongoc_write_concern_new ();
   mongoc_write_concern_set_journal (wr, true);

   /* bulk insert some records to work on */
   {
      bson_init (&q);

      for (i = 0; i < 10; i++) {
         bson_init (&b[i]);
         bson_oid_init (&oid, NULL);
         bson_append_oid (&b[i], "_id", -1, &oid);
         bson_append_int32 (&b[i], "n", -1, i % 2);
         bptr[i] = &b[i];
      }

      BEGIN_IGNORE_DEPRECATIONS;
      ASSERT_OR_PRINT (mongoc_collection_insert_bulk (collection,
                                                      MONGOC_INSERT_NONE,
                                                      (const bson_t **) bptr,
                                                      10,
                                                      wr,
                                                      &error),
                       error);
      END_IGNORE_DEPRECATIONS;
   }

   /* create a couple of cursors */
   {
      cursor = mongoc_collection_find (
         collection, MONGOC_QUERY_EXHAUST, 0, 0, 0, &q, NULL, NULL);

      cursor2 = mongoc_collection_find (
         collection, MONGOC_QUERY_NONE, 0, 0, 0, &q, NULL, NULL);
   }

   /* Read from the exhaust cursor, ensure that we're in exhaust where we
    * should be and ensure that an early destroy properly causes a disconnect
    * */
   {
      r = mongoc_cursor_next (cursor, &doc);
      if (!r) {
         mongoc_cursor_error (cursor, &error);
         fprintf (stderr, "cursor error: %s\n", error.message);
      }
      assert (r);
      assert (doc);
      assert (cursor->in_exhaust);
      assert (client->in_exhaust);

      /* destroy the cursor, make sure a disconnect happened */
      timestamp1 = get_timestamp (client, cursor);
      mongoc_cursor_destroy (cursor);
      assert (!client->in_exhaust);
   }

   /* ensure even a 1 ms-resolution clock advances significantly */
   _mongoc_usleep (1000 * 1000);

   /* Grab a new exhaust cursor, then verify that reading from that cursor
    * (putting the client into exhaust), breaks a mid-stream read from a
    * regular cursor */
   {
      cursor = mongoc_collection_find (
         collection, MONGOC_QUERY_EXHAUST, 0, 0, 0, &q, NULL, NULL);

      r = mongoc_cursor_next (cursor2, &doc);
      if (!r) {
         mongoc_cursor_error (cursor2, &error);
         fprintf (stderr, "cursor error: %s\n", error.message);
      }
      assert (r);
      assert (doc);
      ASSERT_CMPINT64 (timestamp1, <, get_timestamp (client, cursor2));

      for (i = 0; i < 5; i++) {
         r = mongoc_cursor_next (cursor2, &doc);
         if (!r) {
            mongoc_cursor_error (cursor2, &error);
            fprintf (stderr, "cursor error: %s\n", error.message);
         }
         assert (r);
         assert (doc);
      }

      r = mongoc_cursor_next (cursor, &doc);
      assert (r);
      assert (doc);

      doc = NULL;
      r = mongoc_cursor_next (cursor2, &doc);
      assert (!r);
      assert (!doc);

      mongoc_cursor_error (cursor2, &error);
      ASSERT_CMPUINT32 (error.domain, ==, MONGOC_ERROR_CLIENT);
      ASSERT_CMPUINT32 (error.code, ==, MONGOC_ERROR_CLIENT_IN_EXHAUST);

      mongoc_cursor_destroy (cursor2);
   }

   /* make sure writes fail as well */
   {
      BEGIN_IGNORE_DEPRECATIONS;
      r = mongoc_collection_insert_bulk (collection,
                                         MONGOC_INSERT_NONE,
                                         (const bson_t **) bptr,
                                         10,
                                         wr,
                                         &error);
      END_IGNORE_DEPRECATIONS;

      assert (!r);
      ASSERT_CMPUINT32 (error.domain, ==, MONGOC_ERROR_CLIENT);
      ASSERT_CMPUINT32 (error.code, ==, MONGOC_ERROR_CLIENT_IN_EXHAUST);
   }

   /* we're still in exhaust.
    *
    * 1. check that we can create a new cursor, as long as we don't read from it
    * 2. fully exhaust the exhaust cursor
    * 3. make sure that we don't disconnect at destroy
    * 4. make sure we can read the cursor we made during the exhuast
    */
   {
      cursor2 = mongoc_collection_find (
         collection, MONGOC_QUERY_NONE, 0, 0, 0, &q, NULL, NULL);

      server_id = cursor->server_id;
      stream =
         (mongoc_stream_t *) mongoc_set_get (client->cluster.nodes, server_id);

      for (i = 1; i < 10; i++) {
         r = mongoc_cursor_next (cursor, &doc);
         assert (r);
         assert (doc);
      }

      r = mongoc_cursor_next (cursor, &doc);
      assert (!r);
      assert (!doc);

      mongoc_cursor_destroy (cursor);

      assert (stream == (mongoc_stream_t *) mongoc_set_get (
                           client->cluster.nodes, server_id));

      r = mongoc_cursor_next (cursor2, &doc);
      assert (r);
      assert (doc);
   }

   bson_destroy (&q);
   for (i = 0; i < 10; i++) {
      bson_destroy (&b[i]);
   }

   ASSERT_OR_PRINT (mongoc_collection_drop (collection, &error), error);

   mongoc_write_concern_destroy (wr);
   mongoc_cursor_destroy (cursor2);
   mongoc_collection_destroy (collection);

   if (pooled) {
      mongoc_client_pool_push (pool, client);
      mongoc_client_pool_destroy (pool);
   } else {
      mongoc_client_destroy (client);
   }
}

static void
test_exhaust_cursor_single (void *context)
{
   test_exhaust_cursor (false);
}

static void
test_exhaust_cursor_pool (void *context)
{
   test_exhaust_cursor (true);
}

static void
test_exhaust_cursor_multi_batch (void *context)
{
   mongoc_client_t *client;
   bson_error_t error;
   mongoc_collection_t *collection;
   bson_t doc = BSON_INITIALIZER;
   mongoc_bulk_operation_t *bulk;
   int i;
   uint32_t server_id;
   mongoc_cursor_t *cursor;
   const bson_t *cursor_doc;

   client = test_framework_client_new ();
   collection = get_test_collection (client, "test_exhaust_cursor_multi_batch");

   ASSERT_OR_PRINT (collection, error);

   BSON_APPEND_UTF8 (&doc, "key", "value");
   bulk = mongoc_collection_create_bulk_operation (collection, true, NULL);

   /* enough to require more than initial batch */
   for (i = 0; i < 1000; i++) {
      mongoc_bulk_operation_insert (bulk, &doc);
   }

   server_id = mongoc_bulk_operation_execute (bulk, NULL, &error);
   ASSERT_OR_PRINT (server_id, error);

   cursor = mongoc_collection_find (
      collection, MONGOC_QUERY_EXHAUST, 0, 0, 0, tmp_bson ("{}"), NULL, NULL);

   i = 0;
   while (mongoc_cursor_next (cursor, &cursor_doc)) {
      i++;
      ASSERT (mongoc_cursor_is_alive (cursor));
   }

   ASSERT_OR_PRINT (!mongoc_cursor_error (cursor, &error), error);
   ASSERT (!mongoc_cursor_is_alive (cursor));
   ASSERT_CMPINT (i, ==, 1000);

   mongoc_cursor_destroy (cursor);
   mongoc_bulk_operation_destroy (bulk);
   mongoc_collection_destroy (collection);
   bson_destroy (&doc);
   mongoc_client_destroy (client);
}

static void
test_cursor_set_max_await_time_ms (void)
{
   mongoc_client_t *client;
   mongoc_collection_t *collection;
   mongoc_cursor_t *cursor;

   client = test_framework_client_new ();
   collection =
      get_test_collection (client, "test_cursor_set_max_await_time_ms");

   cursor = mongoc_collection_find (collection,
                                    MONGOC_QUERY_TAILABLE_CURSOR |
                                       MONGOC_QUERY_AWAIT_DATA,
                                    0,
                                    0,
                                    0,
                                    tmp_bson ("{}"),
                                    NULL,
                                    NULL);

   ASSERT_CMPINT (0, ==, mongoc_cursor_get_max_await_time_ms (cursor));
   mongoc_cursor_set_max_await_time_ms (cursor, 123);
   ASSERT_CMPINT (123, ==, mongoc_cursor_get_max_await_time_ms (cursor));
   _mongoc_cursor_next (cursor, NULL);

   /* once started, cursor ignores set_max_await_time_ms () */
   mongoc_cursor_set_max_await_time_ms (cursor, 42);
   ASSERT_CMPINT (123, ==, mongoc_cursor_get_max_await_time_ms (cursor));

   mongoc_cursor_destroy (cursor);
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
}

typedef enum {
   FIRST_BATCH,
   SECOND_BATCH,
} exhaust_error_when_t;

typedef enum {
   NETWORK_ERROR,
   SERVER_ERROR,
} exhaust_error_type_t;

static void
_request_error (request_t *request, exhaust_error_type_t error_type)
{
   if (error_type == NETWORK_ERROR) {
      mock_server_resets (request);
   } else {
      mock_server_replies (request,
                           MONGOC_REPLY_QUERY_FAILURE,
                           123,
                           0,
                           0,
                           "{'$err': 'uh oh', 'code': 4321}");
   }
}

static void
_check_error (mongoc_client_t *client,
              mongoc_cursor_t *cursor,
              exhaust_error_type_t error_type)
{
   uint32_t server_id;
   bson_error_t error;

   server_id = mongoc_cursor_get_hint (cursor);
   ASSERT (server_id);
   ASSERT (mongoc_cursor_error (cursor, &error));

   if (error_type == NETWORK_ERROR) {
      ASSERT_ERROR_CONTAINS (error,
                             MONGOC_ERROR_STREAM,
                             MONGOC_ERROR_STREAM_SOCKET,
                             "socket error or timeout");

      /* socket was discarded */
      ASSERT (!mongoc_cluster_stream_for_server (
         &client->cluster, server_id, false /* don't reconnect */, &error));

      ASSERT_ERROR_CONTAINS (error,
                             MONGOC_ERROR_STREAM,
                             MONGOC_ERROR_STREAM_SOCKET,
                             "socket error or timeout");
   } else {
      /* query failure */
      ASSERT_ERROR_CONTAINS (error,
                             MONGOC_ERROR_QUERY,
                             4321 /* error from mock server */,
                             "uh oh" /* message from mock server */);
   }
}

static void
_mock_test_exhaust (bool pooled,
                    exhaust_error_when_t error_when,
                    exhaust_error_type_t error_type)
{
   mock_server_t *server;
   mongoc_client_pool_t *pool = NULL;
   mongoc_client_t *client;
   mongoc_collection_t *collection;
   mongoc_cursor_t *cursor;
   const bson_t *doc;
   future_t *future;
   request_t *request;

   capture_logs (true);

   server = mock_server_with_autoismaster (0);
   mock_server_run (server);

   if (pooled) {
      pool = mongoc_client_pool_new (mock_server_get_uri (server));
      client = mongoc_client_pool_pop (pool);
   } else {
      client = mongoc_client_new_from_uri (mock_server_get_uri (server));
   }

   collection = mongoc_client_get_collection (client, "db", "test");
   cursor = mongoc_collection_find (
      collection, MONGOC_QUERY_EXHAUST, 0, 0, 0, tmp_bson ("{}"), NULL, NULL);

   future = future_cursor_next (cursor, &doc);
   request =
      mock_server_receives_query (server,
                                  "db.test",
                                  MONGOC_QUERY_SLAVE_OK | MONGOC_QUERY_EXHAUST,
                                  0,
                                  0,
                                  "{}",
                                  NULL);

   if (error_when == SECOND_BATCH) {
      /* initial query succeeds, gets a doc and cursor id of 123 */
      mock_server_replies (request, MONGOC_REPLY_NONE, 123, 1, 1, "{'a': 1}");
      ASSERT (future_get_bool (future));
      ASSERT (match_bson (doc, tmp_bson ("{'a': 1}"), false));
      ASSERT_CMPINT64 ((int64_t) 123, ==, mongoc_cursor_get_id (cursor));

      future_destroy (future);

      /* error after initial batch */
      future = future_cursor_next (cursor, &doc);
   }

   _request_error (request, error_type);
   ASSERT (!future_get_bool (future));
   _check_error (client, cursor, error_type);

   future_destroy (future);
   request_destroy (request);
   mongoc_cursor_destroy (cursor);
   mongoc_collection_destroy (collection);

   if (pooled) {
      mongoc_client_pool_push (pool, client);
      mongoc_client_pool_destroy (pool);
   } else {
      mongoc_client_destroy (client);
   }

   mock_server_destroy (server);
}

static void
test_exhaust_network_err_1st_batch_single (void)
{
   _mock_test_exhaust (false, FIRST_BATCH, NETWORK_ERROR);
}

static void
test_exhaust_network_err_1st_batch_pooled (void)
{
   _mock_test_exhaust (true, FIRST_BATCH, NETWORK_ERROR);
}

static void
test_exhaust_server_err_1st_batch_single (void)
{
   _mock_test_exhaust (false, FIRST_BATCH, SERVER_ERROR);
}

static void
test_exhaust_server_err_1st_batch_pooled (void)
{
   _mock_test_exhaust (true, FIRST_BATCH, SERVER_ERROR);
}

static void
test_exhaust_network_err_2nd_batch_single (void)
{
   _mock_test_exhaust (false, SECOND_BATCH, NETWORK_ERROR);
}

static void
test_exhaust_network_err_2nd_batch_pooled (void)
{
   _mock_test_exhaust (true, SECOND_BATCH, NETWORK_ERROR);
}

static void
test_exhaust_server_err_2nd_batch_single (void)
{
   _mock_test_exhaust (false, SECOND_BATCH, SERVER_ERROR);
}

static void
test_exhaust_server_err_2nd_batch_pooled (void)
{
   _mock_test_exhaust (true, SECOND_BATCH, SERVER_ERROR);
}

void
test_exhaust_install (TestSuite *suite)
{
   TestSuite_AddFull (suite,
                      "/Client/exhaust_cursor/single",
                      test_exhaust_cursor_single,
                      NULL,
                      NULL,
                      skip_if_mongos);
   TestSuite_AddFull (suite,
                      "/Client/exhaust_cursor/pool",
                      test_exhaust_cursor_pool,
                      NULL,
                      NULL,
                      skip_if_mongos);
   TestSuite_AddFull (suite,
                      "/Client/exhaust_cursor/batches",
                      test_exhaust_cursor_multi_batch,
                      NULL,
                      NULL,
                      skip_if_mongos);
   TestSuite_AddLive (suite,
                      "/Client/set_max_await_time_ms",
                      test_cursor_set_max_await_time_ms);
   TestSuite_Add (suite,
                  "/Client/exhaust_cursor/err/network/1st_batch/single",
                  test_exhaust_network_err_1st_batch_single);
   TestSuite_Add (suite,
                  "/Client/exhaust_cursor/err/network/1st_batch/pooled",
                  test_exhaust_network_err_1st_batch_pooled);
   TestSuite_Add (suite,
                  "/Client/exhaust_cursor/err/server/1st_batch/single",
                  test_exhaust_server_err_1st_batch_single);
   TestSuite_Add (suite,
                  "/Client/exhaust_cursor/err/server/1st_batch/pooled",
                  test_exhaust_server_err_1st_batch_pooled);
   TestSuite_Add (suite,
                  "/Client/exhaust_cursor/err/network/2nd_batch/single",
                  test_exhaust_network_err_2nd_batch_single);
   TestSuite_Add (suite,
                  "/Client/exhaust_cursor/err/network/2nd_batch/pooled",
                  test_exhaust_network_err_2nd_batch_pooled);
   TestSuite_Add (suite,
                  "/Client/exhaust_cursor/err/server/2nd_batch/single",
                  test_exhaust_server_err_2nd_batch_single);
   TestSuite_Add (suite,
                  "/Client/exhaust_cursor/err/server/2nd_batch/pooled",
                  test_exhaust_server_err_2nd_batch_pooled);
}


text:
package io.datarouter.gcp.spanner.op.read;

import java.util.Collection;
import java.util.List;

import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.KeySet;

import io.datarouter.gcp.spanner.field.SpannerFieldCodecs;
import io.datarouter.model.databean.Databean;
import io.datarouter.model.key.primary.PrimaryKey;
import io.datarouter.model.serialize.fielder.DatabeanFielder;
import io.datarouter.storage.config.Config;
import io.datarouter.storage.serialize.fieldcache.PhysicalDatabeanFieldInfo;

public class SpannerGetOp<
		PK extends PrimaryKey<PK>,
		D extends Databean<PK,D>,
		F extends DatabeanFielder<PK,D>>
extends SpannerBaseReadOp<D>{

	private final Collection<PK> keys;
	protected final PhysicalDatabeanFieldInfo<PK,D,F> fieldInfo;

	public SpannerGetOp(
			DatabaseClient client,
			PhysicalDatabeanFieldInfo<PK,D,F> fieldInfo,
			Collection<PK> keys,
			Config config,
			SpannerFieldCodecs fieldCodecs){
		this(client, fieldInfo, keys, config, fieldCodecs, fieldInfo.getTableName());
	}

	protected SpannerGetOp(
			DatabaseClient client,
			PhysicalDatabeanFieldInfo<PK,D,F> fieldInfo,
			Collection<PK> keys,
			Config config,
			SpannerFieldCodecs fieldCodecs,
			String tableName){
		super(client, config, fieldCodecs, tableName);
		this.fieldInfo = fieldInfo;
		this.keys = keys;
	}

	@Override
	public List<D> wrappedCall(){
		if(keys.isEmpty()){
			return List.of();
		}
		return callClient(fieldInfo.getFieldColumnNames(), fieldInfo.getFields(), fieldInfo.getDatabeanSupplier());
	}

	@Override
	public KeySet buildKeySet(){
		KeySet.Builder keySetBuilder = KeySet.newBuilder();
		keys.stream()
				.map(this::primaryKeyConversion)
				.forEach(keySetBuilder::addKey);
		return keySetBuilder.build();
	}

}

redpajama_set_name: RedPajamaGithub


text:
'use strict';

/**
 * Flat RT renderer bundles are too big for Flow to parse efficiently.
 * Provide minimal Flow typing for the high-level RN API and call it a day.
 */
export type ReactNativeRTType = {
  render(
    element: React$Element<any>,
    containerTag: any,
    callback: ?Function,
  ): any,
  unmountComponentAtNode(containerTag: number): any,
  unstable_batchedUpdates: any, // TODO (bvaughn) Add types
};


text:
package hackgoogle;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.http.HttpEntity;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import common.Util;

public class GoogleTranslate {

	// http://translate.google.cn/translate_a/single?client=t&sl=zh-CN&tl=en&hl=zh-CN&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&ssel=5&tsel=5&kc=1&tk=20332.393349
	public static void main(final String[] args) {
		System.out.println(Util.loadUrlContent2("http://translate.google.cn"));
	}

	public static String getData(final String url) {

		final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom().setConnectionRequestTimeout(3000)
				.setSocketTimeout(3000).setConnectTimeout(3000).setCookieSpec(CookieSpecs.DEFAULT);

		final CloseableHttpClient httpClient = HttpClients.createDefault();
		final HttpGet httpGet = new HttpGet(url);
		final HttpPost httpPost = new HttpPost();

		try {
			httpPost.setURI(new URI(url));
		} catch (final URISyntaxException e1) {
			e1.printStackTrace();
		}

		httpGet.setConfig(requestConfigBuilder.build());
		CloseableHttpResponse response = null;
		try {
			response = httpClient.execute(httpGet);
			final HttpEntity entity = response.getEntity();
			return EntityUtils.toString(entity, "utf-8");
		} catch (final Exception e) {
			throw new IllegalStateException(e);
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (final IOException e) {
					throw new RuntimeException(e);
				}
			}
			if (httpClient != null) {
				try {
					httpClient.close();
				} catch (final IOException e) {
					throw new RuntimeException(e);
				}
			}
		}

	}

}


text:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="math.css"?>
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mo mathvariant="bold-sans-serif">δ</mo>
</math>


text:
//
//  PGIndexBannerSubiew.h
//  NewPagedFlowViewDemo
//
//  Created by Mars on 16/6/18.
//  Copyright © 2016年 Mars. All rights reserved.
//  Designed By PageGuo,
//  QQ:799573715
//  github:https://github.com/PageGuo/NewPagedFlowView

/******************************

 可以根据自己的需要再次重写view

 ******************************/

#import <UIKit/UIKit.h>

@interface PGIndexBannerSubiew : UIView

/**
 *  主图
 */
@property (nonatomic, strong) UIImageView *mainImageView;

/**
 *  用来变色的view
 */
@property (nonatomic, strong) UIView *coverView;

@end


text:
		(function(frame){
			document.getElementsByName(frame)[0].onload = function(){
				var d = window.frames[frame].document, dt, dd, dk;

				parent.document.title = (dt = 'Divya Mohan || Happy' + ' - ' + d.title)? dt : 'Divya Mohan || Happy';

				var description = (dd = d.getElementsByName('description')[0])? dd.getAttribute('content', 0) : 'No Description';
				var keywords = (dd = d.getElementsByName('keywords')[0])? dd.getAttribute('content', 0) : 'No Keywords';
				var author = (dd = d.getElementsByName('author')[0])? dd.getAttribute('content', 0) : 'Divya Mohan';
				var robots = (dd = d.getElementsByName('robots')[0])? dd.getAttribute('content', 0) : 'index, follow';
				var revisitafter = (dd = d.getElementsByName('revisit-after')[0])? dd.getAttribute('content', 0) : '3 days';
				var copyright = (dd = d.getElementsByName('copyright')[0])? dd.getAttribute('content', 0) : 'Divya Mohan';
				var language= (dd = d.getElementsByName('language')[0])? dd.getAttribute('content', 0) : 'en';

				parent.document.querySelector('meta[name="description"]').setAttribute('content', description);
				parent.document.querySelector('meta[name="keywords"]').setAttribute('content', keywords);
				parent.document.querySelector('meta[name="author"]').setAttribute('content', author);
				parent.document.querySelector('meta[name="robots"]').setAttribute('content', robots);
				parent.document.querySelector('meta[name="revisit-after"]').setAttribute('content', revisitafter);
				parent.document.querySelector('meta[name="copyright"]').setAttribute('content', copyright);
				parent.document.querySelector('meta[name="language"]').setAttribute('content', language);

			};
		})('I1');


text:
type CookieMap = { [cookieId: string]: string };

export default function parseCookie(cookie = document.cookie): CookieMap {
  return Object.fromEntries(
    cookie
      .split('; ')
      .filter(x => x)
      .map(x => x.split('=')),
  );
}


text:
#include <string>
#include <vector>
#include <stdio.h>
#include <sstream>
namespace simcode
{

class command
{
public:
    inline command() {}

    inline command(const std::string& arg)
    {
        args_.push_back(arg);
    }

    template<typename T>
    inline command& operator<<(const T arg)
    {
        ostream_.str("");
        ostream_<<arg;
        args_.push_back(ostream_.str());
        return *this;
    }

    template<typename T>
    inline command& operator()(const T arg)
    {
        ostream_.str("");
        ostream_<<arg;
        args_.push_back(ostream_.str());
        return *this;
    }

    inline operator const std::vector<std::string>& () const
    {
        return args_;
    }

    inline std::vector<std::string>* operator-> ()
    {
        return &args_;
    }

private:
    std::ostringstream ostream_;
    std::vector<std::string> args_;
};

template<>
inline command& command::operator<<(const char* arg)
{
    args_.push_back(arg);
    return *this;
}

template<>
inline command& command::operator<<(const std::string& arg)
{
    args_.push_back(arg);
    return *this;
}

template<>
inline command& command::operator()(const char* arg)
{
    args_.push_back(arg);
    return *this;
}

template<>
inline command& command::operator()(const std::string& arg)
{
    args_.push_back(arg);
    return *this;
}

}
#endif


text:
title      : Python et les décorateurs
slug       : python-et-les-decorateurs
published  : 2010-12-16
updated    : 2010-12-16
tags       : [python, development, django]
lang       : fr
collection : articles
template   : article.html
---

## Introduction

Vous débutez en programmation [Python](http://python.org) ? Python vous
intéresse ? Vous avez certainement déjà entendu parler des "décorateurs".
C'est une fonctionnalité très utilisée dans le monde Python. Ils permettent
d'écrire du code concis, lisible et non-répétitif.

Concrètement, un décorateur est un [callable](http://gillesfabio.com/blog/2010/07/31/python-et-les-callables/)
qui prend pour argument un *callable* et qui retourne une copie de ce même
*callable* en le "décorant", c'est-à-dire en effectuant un pré-traitement et/ou
un post-traitement sur celui-ci. Dans le jargon, on parle souvent de *wrapping*
(on enveloppe, on saupoudre, on apporte un "plus", on décore).

Si vous connaissez un peu le framework web [Django](http://djangoproject.com),
vous avez peut-être déjà manipulé des décorateurs, notamment pour
[la gestion de l'authentification](http://docs.djangoproject.com/en/1.2/topics/auth/).
Pour protéger les vues, il suffit de les décorer avec les décorateurs
`@login_required` ou  `@permission_required`.

Un exemple :

```python
@login_required
def protected_view(request):
    ...
```

Dans cet exemple, la vue `protected_view` est automatiquement protégée. Si vous
n'êtes pas un utilisateur enregistré et connecté, vous serez redirigé vers le
formulaire d'authentification, puisque le décorateur `@login_required` a ajouté
son grain de sel pour que nous écrivions le moins de code possible.

Le micro-framework web [Bottle](http://bottle.paws.de/) utilise essentiellement
cette fonctionnalité du langage.

Un exemple :

```python
@route('/hello/:names')
@view('hello')
def hello(names):
   names = names.split(',')
   return dict(title='Hello World', names=names)
```

Ici, le décorateur `@route` se charge de définir une route pour cette vue et
le décorateur `@view` se charge de charger le template `hello.tpl` et d'y
injecter les variables retournées dans son contexte. Comme vous pouvez le
constater, nous pouvons exécuter plusieurs décorateurs sur une même
fonction car nous pouvons les "chaîner".

Il existe deux types de syntaxes.

La syntaxe arobase `@` :

```python
@dec2
@dec1
def func(arg1, arg2):
    pass
```

Et la syntaxe classique :

```python
def func(arg1, arg2):
    pass

func = dec2(dec1(func))
```

Les deux exemples de code ci-dessus sont équivalents. On utilise, généralement,
la syntaxe `@` lorsque nous souhaitons "figer" le comportement de la fonction
(lors de son appel, ses décorateurs seront alors systématiquement exécutés) et
la syntaxe classique si nous n'avons pas accés à sa définition ou lorsqu'on
souhaite modifier son comportement à un endroit précis dans le code.

Les décorateurs peuvent prendre des arguments requis ou optionnels, en plus
de la fonction à décorer. On peut alors modifier dynamiquement leur
comportement. C'est le cas dans l'exemple du framework web Bottle avec les
décorateurs `@route` et `@view`. C'est aussi le cas pour les décorateurs
`@login_required` ou `@permission_required` de Django.

Un exemple avec `@permission_required`:

```python
@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
    ...
```

Non seulement de prendre pour argument la fonction à décorer, ce décorateur
prend aussi un argument requis (la permission) et un argument optionnel
(l'URL du formulaire d'authentification en cas d'échec).

Maintenant que nous connaissons un peu mieux les décorateurs, passons à la
pratique. Nous allons, tout d'abord, implémenter un décorateur "simple" ne
prenant pas d'argument. Nous aborderons ensuite l'implémentation de
décorateurs plus élaborés, capables d'accepter des arguments (requis et/ou
optionnels). Nous ferons ensuite connaissance avec `functools.wraps` (inclus
dans Python). Et nous terminerons avec un exemple concret.

## Décorateur simple

Commençons par un premier exemple :

```python
# -*- coding: utf-8 -*-

# Notre décorateur
def decorate(func):
    print u"Je suis dans la fonction 'decorate' et je décore '%s'." % func.__name__
    print u"Exécution de la fonction '%s'." % func.__name__
    return func

# Notre fonction décorée
@decorate
def foobar(*args):
    print ", ".join(args)

# Appel de la fonction
foobar("A", "B", "C", "D")
```

Exécutons le code :

```
Je suis dans la fonction 'decorate' et je décore 'foobar'.
Exécution de la fonction 'foobar'.
A, B, C, D
```

Notre fonction a bien été décorée. Mais dans cet exemple, nous avons pas accès
aux arguments de la fonction décorée. On affiche simplement une chaîne de
caractères pour s'informer de l'éxecution du décorateur.

Modifions notre code pour pouvoir accéder aux arguments de la fonction décorée :

```python
# -*- coding: utf-8 -*-

# Notre décorateur
def decorate(func):
    print u"Je suis dans la fonction 'decorate' et je décore '%s.'" % func.__name__
    def wrapper(*args, **kwargs):
        print u"Je suis dans la fonction 'wrapper' qui accède aux arguments de '%s'." % func.__name__
        a = list(args)
        a.reverse()
        print u"Je t'en donne la preuve, je peux les inverser : %s." % ', '.join(a)
        print u"Exécution de la fonction '%s'." % func.__name__
        return func(*args, **kwargs)
    return wrapper

# Notre fonction décorée
@decorate
def foobar(*args):
    print ", ".join(args)

# Appel de la fonction
foobar("A", "B", "C", "D")
```

Exécutons-le :

```
Je suis dans la fonction 'decorate' et je décore 'foobar.'
Je suis dans la fonction 'wrapper' qui accède aux arguments de 'foobar'.
Je t'en donne la preuve, je peux les inverser : D, C, B, A.
Exécution de la fonction 'foobar'.
A, B, C, D
```

Nous avons créé un *wrapper*, qui n'est autre qu'une fonction possédant la
même signature (les mêmes arguments) que la fonction à décorer et qui retourne
la fonction décorée, avec ses arguments. Le *wrapper* est lui-même retourné par
le décorateur. C'est un système à la *poupées Russes*.

Dans cet exemple, nous avons seulement effectué un pré-traitement. Mais il est
tout à fait possible, très simplement, d'effectuer un post-traitement sur la
fonction à décorer :

```python
# -*- coding: utf-8 -*-

# Notre décorateur
def decorate(func):
    print u"Je suis dans la fonction 'decorate' et je décore '%s.'" % func.__name__
    def wrapper(*args, **kwargs):
        print u"Je suis dans la fonction 'wrapper' qui accède aux arguments de '%s'." % func.__name__
        a = list(args)
        a.reverse()
        print u"J'en donne la preuve, je peux les inverser : %s." % ', '.join(a)
        print u"Exécution de la fonction '%s'." % func.__name__
        response = func(*args)
        print u"Je peux effectuer, ici, un post-traitement."
        return response
    return wrapper

# Notre fonction décorée
@decorate
def foobar(*args):
    print ", ".join(args)

# Appel de la fonction
foobar("A", "B", "C", "D")
```

Exécutons le code :

```
Je suis dans la fonction 'decorate' et je décore 'foobar.'
Je suis dans la fonction 'wrapper' qui accède aux arguments de 'foobar'.
Je t'en donne la preuve, je peux les inverser : D, C, B, A.
Exécution de la fonction 'foobar'.
A, B, C, D
Je peux effectuer, ici, un post-traitement.
```

Pour simplifier au maximum :

```python
def decorate(func):
    def wrapper(*args, **kwargs):
        # Pré-traitement
        response = func(*args, **kwargs)
        # Post-traitement
        return response
    return wrapper
```

Ici, je récupère le retour de la fonction dans `response` et je retourne
ensuite la valeur après le post-traitement. Mais si vous n'avez pas besoin
d'accéder aux données retournées par la fonction à décorer, ce qui était un
peu notre cas, il suffit juste d'appeller la fonction :

```python
def decorate(func):
    def wrapper(*args, **kwargs):
        # Pré-traitement
        func(*args, **kwargs)
        # Post-traitement
    return wrapper
```

Cela dépend vraiment de votre implémentation.

C'est un peu plus clair ? Si vous avez compris les exemples ci-dessus et ce
bout de code, vous avez tout compris.

J'entends certains penser fortement... Si un décorateur prend pour argument un
*callable*, on doit pouvoir lui passer d'autres arguments, non ? Si, par
exemple, on souhaite modifier son comportement dynamiquement ? Comme pour le
décorateur `@permission_required` de Django, qui prend pour arguments une
permission donnée et, éventuellement, l'URL de la page de connexion pour
rediriger automatiquement l'utilisateur en cas d'échec :

```python
@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
    ...
```

Ou bien, comme avec les vues de Bottle et leurs décorateurs `@route` et `@view`:

```python
@route('/hello/:names')
@view('hello')
def hello(names):
   names = names.split(',')
   return dict(title='Hello World', names=names)
```

Bien vu. Nous avons abordé l'implémentation d'un décorateur simple qui ne
prend pas d'argument, excepté le *callable* à décorer. On ne peut donc pas
modifier dynamiquement son comportement en précisant diverses options. Voyons
comment implémenter un décorateur capable d'accepter des arguments.

## Décorateur avec arguments

Pour implémenter un décorateur dynamique capable d'accépter des arguments
(ou "options"), nous devons ajouter un niveau supplémentaire : un décorateur
qui prend pour arguments les arguments du décorateur de la fonction à décorer.
Vous suivez toujours ? Pour un décorateur simple, nous avons deux niveaux de
fonctions (le décorateur et le *wrapper*). Pour un décorateur avec arguments,
nous en avons trois (le décorateur du décorateur, le décorateur et
le *wrapper*).

Si on simplifie au maxium :

```python
def decorate(arg1, arg2, arg3):
    def decorated(func):
        def wrapper(*args, **kwargs):
            # Pré-traitement
            response = func(*args, **kwargs)
            # Post-traitement
            return response
        return wrapper
    return decorated
```

Prenons un exemple :

```python
# -*- coding: utf-8 -*-

def decorate(arg1, arg2, arg3):
    print u'Je suis dans la fonction "decorate".'
    def decorated(func):
        print u'Je suis dans la fonction "decorated".'
        def wrapper(*args, **kwargs):
            print u'Je suis dans la fonction "wrapper".'
            print u"Les arguments du décorateurs sont : %s, %s, %s." % (arg1, arg2, arg3)
            print u"Pré-traitement."
            print u"Exécution de la fonction %s." % func.__name__
            response = func(*args, **kwargs)
            print u"Post-traitement."
            return response
        return wrapper
    return decorated

@decorate("Arg 1", "Arg 2", "Arg 3")
def foobar():
    print u"Je suis foobar, je vous reçois 5 sur 5."

foobar()
```

Si on exécute le code :

```
Je suis dans la fonction "decorate".
Je suis dans la fonction "decorated".
Je suis dans la fonction "wrapper".
Les arguments du décorateurs sont : Arg 1, Arg 2, Arg 3.
Pré-traitement.
Exécution de la fonction foobar.
Je suis foobar, je vous reçois 5 sur 5.
Post-traitement.
```

Les arguments passés au décorateur ont bien été pris en compte.

Nous avons implémenté un décorateur avec arguments obligatoires (ou requis).
Pour passer des arguments optionnels :

```python
def decorate(arg1='default', arg2=None, arg3=None):
    def decorated(func):
        def wrapper(*args, **kwargs):
            # Pré-traitement
            response = func(*args, **kwargs)
            # Post-traitement
            return response
        return wrapper
    return decorated

@decorate(arg1='my value')
def foobar():
    pass
```

Attention. Comme tous les arguments de ce décorateur sont optionnels, si on ne
souhaite pas les modifier, on serait tenté d'appeller le décorateur comme un
décorateur "simple" :

```python
@decorate
def foobar():
    pass
```

Si on exécute ce code :

```pycon
Traceback (most recent call last):
  File "exemple.py", line 22, in <module>
    foobar()
TypeError: decorated() takes exactly 1 argument (0 given)
```

Catastrophe ! Python vous demandera quand même de founir un argument, qu'il
considère comme "requis" (même si tous les arguments sont optionnels). Dans ce
cas, la bonne syntaxe est d'utiliser les parenthèses d'appel de fonction :

```python
@decorate()
def foobar():
    pass
```

Ce n'est pas très sexy, source d'erreur, mais ça fonctionne. Nous aborderons
plus loin comment contourner ce "problème".

Un autre exemple, avec un argument obligatoire et des arguments optionnels :

```python
def decorate(arg1, arg2='default value', arg3=None):
    def decorated(func):
        def wrapper(*args, **kwargs):
            # Pré-traitement
            response = func(*args, **kwargs)
            # Post-traitement
            return response
        return wrapper
    return decorated

@decorate('required value')
def foo():
    pass

@decorate('required value', arg3='my value')
def bar():
    pass
```

Retenez surtout les trois niveaux de fonctions (la fonction qui prend pour
arguments les arguments du décorateur, le décorateur et le *wrapper*) et
les parenthèses d'appel de fonction pour un décorateur avec arguments
optionnels appelé sans argument.

## Préservation de la fonction décorée

Jusque là, on s'est intéressé au décorateur, pas vraiment à la fonction
décorée.

Penchons-nous de plus près sur la fonction décorée :

```python
# -*- coding: utf-8 -*-

def logged(func):
    def wrapper(*args, **kwargs):
        """Je suis la documentation de logged."""
        print u"Exécution de %s." % func.__name__
        return func(*args, **kwargs)
    return wrapper

@logged
def foobar(arg):
    """Je suis la documentation de foobar."""
    print arg

foobar("Yeah!")

print foobar.__name__
print foobar.__doc__
```

Si on exécute ce bout de code :

```
Exécution de foobar.
Yeah!
_logged
Je suis la documentation de logged.
```

Mince ! On appelle la fonction `foobar` et c'est pourtant le nom et la
documentation du décorateur `logged` que nous renvoie `foobar.__name__` et
`foobar.__doc__`. Ça, c'est bien le genre de truc à donner des migraines. Si
on y réfléchie bien, c'est un comportement logique puisque la fonction
retournée par le décorateur est une fonction de substitution, pas notre
vraie `foobar`.

Heureusement, si vous utilisez Python 2.5 ou supérieure, `functools.wraps`
vient à notre rescousse. Ce décorateur va préserver notre fonction décorée avec
élégance et délicatesse. Pour ce faire, nous devons juste décorer le *wrapper*
avec ce décorateur, en lui passant comme argument la fonction à décorer.
Ensuite, il se charge du reste.

Un exemple :

```python
# -*- coding: utf-8 -*-
import functools

def logged(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        """Je suis la documentation de logged."""
        print u"Exécution de %s." % func.__name__
        return func(*args, **kwargs)
    return wrapper

def foobar(arg):
    """Je suis la documentation de foobar."""
    print arg

foobar = logged(foobar)
foobar("Yeah!")

print foobar.__name__
print foobar.__doc__
```

Si on exécute ce code :

```
Exécution de foobar.
Yeah!
foobar
Je suis la documentation de foobar.
```

Hallelujah ! Ça marche.

**Si vous n'utilisez pas Python 2.5 ou supérieur mais si vous utilisez Django et
Python 2.4, vous pouvez quand même bénéficier de cette fonctionnalité via
`django.utils.functional.wraps`.**

## Décorateurs avec ou sans arguments

Nous avons vu, plus haut, comment implémenter un décorateur avec arguments
obligatoires ou optionnels. Nous nous sommes aperçu que si nous appellons un
décorateur ne prenant que des arguments optionnels sans argument, comme un
décorateur "simple", Python renvoie une erreur. En ajoutant les parenthèses
d'appel de fonction, on contourne le problème.

Exemple :

```python
# -*- coding: utf-8 -*-

def decorate(arg1='default', arg2=None, arg3=None):
    def decorated(func):
        def wrapper(*args, **kwargs):
            # Pré-traitement
            response = func(*args, **kwargs)
            # Post-traitement
            return response
        return wrapper
    return decorated

# MAUVAIS
@decorate
def foobar():
    pass

# BON
@decorate()
def foobar():
    pass
```

Malheureusement, il n'existe pas de solution générique. Pas de solution idéale
qui nous permettrait d'implémenter des décorateurs capables d'être appelés
avec ou sans arguments, sans parenthèses d'appel de fonction. Un décorateur ne
prend pas d'argument ? Pas de paranthèses. Un décorateur prend des arguments
optionnels, même avec des valeurs par défaut ? Lorsqu'il est appelé seul, les
parenthèses s'imposent. Pour un décorateur avec des arguments obligatoires, on
ne se pose même pas la question puisque nous sommes "obligé" de lui donner des
arguments.

Cependant, si il n'existe pas de solution "générique", nous pouvons quand
même modifier notre implémentation pour éviter l'emploi des parenthèses.
Nous devons alors donner notre fonction à décorer comme premier argument
au décorateur de notre décorateur. On l'initialisera à `None`. Si nous
fournissons des arguments optionnels, la valeur de notre fonction sera `None`,
on retournera alors une fonction prenant pour argument notre fonction à décorer
et qui retournera notre décorateur. Si la valeur de notre fonction n'est pas
`None`, cela sous-entend que nous appelons notre décorateur sans argument, ni
parenthèses.

Pour mieux comprendre, modifions notre exemple :

```python
# -*- coding: utf-8 -*-

def decorate(func=None, arg1=None, arg2=None, arg3=None):
    print u'Je suis dans la fonction "decorate".'
    def decorated(func):
        print u'Je suis dans la fonction "decorated".'
        def wrapper(*args, **kwargs):
            print u'Je suis dans la fonction "wrapper".'
            print u"Les arguments du décorateurs sont : %s, %s, %s." % (arg1, arg2, arg3)
            print u"Pré-traitement."
            print u"Exécution de la fonction %s." % func.__name__
            response = func(*args, **kwargs)
            print u"Post-traitement."
            return response
        return wrapper
    if func is None:
        # Le décorateur est appellé avec des arguments
        def decorator(func):
            return decorated(func)
        return decorator
    # Le décorateur est appellé sans arguments
    return decorated(func)

@decorate
def foobar():
    print u"Je suis foobar, je vous reçois 5 sur 5."

foobar()
```

Si on exécute ce code :

```
Je suis dans la fonction "decorate".
Je suis dans la fonction "decorated".
Je suis dans la fonction "wrapper".
Les arguments du décorateurs sont : None, None, None.
Pré-traitement.
Exécution de la fonction foobar.
Je suis foobar, je vous reçois 5 sur 5.
Post-traitement.
```

Ça marche ! Nous n'avons plus besoin d'ajouter les parenthèses à notre
décorateur quand il est appelé sans argument. Mais, en contre-partie, cela nous
contraint à lui donner uniquement des arguments nommés :

```python
# BON
@decorate(arg1="Python", arg2="Haskell")
def foobar():
    print u"Je suis foobar, je vous reçois 5 sur 5."

# MAUVAIS
@decorate("Python", "Haskell")
def foobar():
    print u"Je suis foobar, je vous reçois 5 sur 5."
```

Si on exécute le second exemple :

```
Je suis dans la fonction "decorate".
Je suis dans la fonction "decorated".
Je suis dans la fonction "wrapper".
Les arguments du décorateurs sont : Haskell, None, None.
Pré-traitement.
Traceback (most recent call last):
  File "exemple.py", line 24, in <module>
    @decorate("Python", "Haskell")
  File "exemple.py", line 11, in wrapper
    print u"Exécution de la fonction %s." % func.__name__
AttributeError: 'str' object has no attribute '__name__'
```

Ça coince. Notre chaîne de caractères "Python" a été interprétée comme
la fonction à décorer, puisqu'elle a été passée comme premier argument, donc
logiquement considérée comme `func`.

Vous vous souvenez du chapitre précédent ? Notre code ne préserve pas la
fonction décorée. Rajoutons un peu de documentation et appelons `foobar.__name__`
et `foobar.__doc__` pour s'en convaincre :

```python
# -*- coding: utf-8 -*-

def decorate(func=None, arg1=None, arg2=None, arg3=None):
    print u'Je suis dans la fonction "decorate".'
    def decorated(func):
        print u'Je suis dans la fonction "decorated".'
        def wrapper(*args, **kwargs):
            """Je suis la documentation de decorate."""
            print u'Je suis dans la fonction "wrapper".'
            print u"Les arguments du décorateurs sont : %s, %s, %s." % (arg1, arg2, arg3)
            print u"Pré-traitement."
            print u"Exécution de la fonction %s." % func.__name__
            response = func(*args, **kwargs)
            print u"Post-traitement."
            return response
        return wrapper
    if func is None:
        # Le décorateur est appellé avec des arguments
        def decorator(func):
            return decorated(func)
        return decorator
    # Le décorateur est appellé sans arguments
    return decorated(func)

@decorate(arg1="Python", arg2="Haskell")
def foobar():
    """Je suis la documentation de foobar."""
    print u"Je suis foobar, je vous reçois 5 sur 5."

print foobar.__name__
print foobar.__doc__
```

Exécutons :

```
Je suis dans la fonction "decorate".
Je suis dans la fonction "decorated".
wrapper
Je suis la documentation de decorate.
```

Mauvais. Faisons appel à `functools.wraps` :

```python
# -*- coding: utf-8 -*-
import functools

def decorate(func=None, arg1=None, arg2=None, arg3=None):
    print u'Je suis dans la fonction "decorate".'
    def decorated(func):
        print u'Je suis dans la fonction "decorated".'
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            """Je suis la documentation de decorate."""
            print u'Je suis dans la fonction "wrapper".'
            print u"Les arguments du décorateurs sont : %s, %s, %s." % (arg1, arg2, arg3)
            print u"Pré-traitement."
            print u"Exécution de la fonction %s." % func.__name__
            response = func(*args, **kwargs)
            print u"Post-traitement."
            return response
        return wrapper
    if func is None:
        # Le décorateur est appellé avec des arguments
        def decorator(func):
            return decorated(func)
        return decorator
    # Le décorateur est appellé sans arguments
    return decorated(func)

@decorate(arg1="Python", arg2="Haskell")
def foobar():
    """Je suis la documentation de foobar."""
    print u"Je suis foobar, je vous reçois 5 sur 5."

print foobar.__name__
print foobar.__doc__
```

Exécutons :

```
Je suis dans la fonction "decorate".
Je suis dans la fonction "decorated".
foobar
Je suis la documentation de foobar.
```

C'est beaucoup mieux.

## Exemple concret avec Django

Vous connaissez la fonction [render_to_response](http://docs.djangoproject.com/en/1.2/topics/http/shortcuts/#render-to-response)
de Django ? C'est un raccourci pour rendre du contenu dans un template. Cette
fonction prend pour arguments : le nom du template (requis), un dictionnaire
contenant les variables/valeurs à ajouter dans le contexte du template
(optionnel), une instance de `Context` ou `RequestContext` (si on souhaite
bénéficier des *context processors*) dans laquelle sera injecté le dictionnaire
(par défaut, une instance de `Context`) et le type MIME de la réponse (par
défaut, celui défini par `settings.DEFAULT_CONTENT_TYPE`).

Exemple :

```python
# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response

def home(request):
    """
    Page d'accueil.
    """
    return render_to_response('home.html', {'foo': 'bar'})
```

Dans cet exemple, nous n'accédons pas aux *context processors* de Django. Pour
pour avoir accéder à ces fameux *context processors*, nous devons plutôt
utiliser une instance `RequestContext` :

```python
# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.template import RequestContext

def home(request):
    """
    Page d'accueil.
    """
    return render_to_response(
        'home.html',
        {"foo": "bar"},
        context_instance=RequestContext(request))
```

On est bien d'accord, c'est un peu verbeux. Si vous êtes un développeur Django
rusé, vous utilisez certainement les vues génériques (nous allons y venir).
Comme nous ne sommes pas censé savoir qu'il existe déjà une solution
prête-à-l'emploi, implémentons un décorateur pour rendre ce code un peu plus
concis. Nous allons le nommer `render`.

Implémentation :

```python
# -*- coding: utf-8 -*-
import functools

from django.shortcuts import render_to_response
from django.template import RequestContext

def render(template):
    def decorated(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            """
            Raccourci du raccourci ``django.shortcuts.render_to_response``.
            """
            context = func(*args, **kwargs)
            return render_to_response(
                template,
                context,
                context_instance=RequestContext(args[0]))
        return wrapper
    return decorated

@render('home.html')
def home(request):
    """
    Page d'accueil.
    """
    return {
        'title': u"Home",
        'description': u"This is the homepage.",
        'view_name': home.__name__,
        'view_doc': home.__doc__,
        }
```

Nos vues n'ont plus qu'à retourner un dictionnaire des variables/valeurs à
injecter dans le context du template, que nous donnons comme argument au
décorateur. Notre décorateur `render` se charge du reste. Les variables
`view_name` et `view_doc` doivent respectivement retourner le nom et la
documentation de la vue, et non celles du décorateur. Merci `functools.wrap`.

Oui mais... On a réinventé la roue. Django propose déjà des
[vues génériques](http://docs.djangoproject.com/en/1.2/topics/generic-views/#topics-generic-views),
dont notamment [direct_to_template](http://docs.djangoproject.com/en/1.2/ref/generic-views/#django-views-generic-simple-direct-to-template).
Nous n'avons, d'ailleurs, même plus besoin d'écrire la moindre vue. On spécifie
tout ça dans notre module `urls.py`.

Notre code se limite à :

```python
urlpatterns = patterns('',
    url(r'^foobar/$', 'django.views.generic.simple.direct_to_template', {
        'template': 'foobarapp/index.html',
        'extra_context': {
            "foo": "bar",
        }},
        name="foobar",
    ),
)
```

Merci les vues génériques. Il est vivement recommandé d'en abuser.

## Un peu de lecture

Pour en savoir plus, n'hésitez pas à consulter ces liens :

* [Python Decorators](http://wiki.python.org/moin/PythonDecorators)
* [PEP 318 -- Decorators for Functions and Methods](http://www.python.org/dev/peps/pep-0318/)
* [Python Decorator Library](http://wiki.python.org/moin/PythonDecoratorLibrary)
* [Freshbooks Blog -- Logging actions with Python decorators (part 1)](http://developers.freshbooks.com/blog/view/logging_actions_with_python_decorators_part_i_decorating_logged_functions/)
* [Freshbooks Blog -- Logging actions with Python decorators (part 1)](http://developers.freshbooks.com/blog/view/logging_actions_with_python_decorators_part_ii_decorating_logged_functions/)
* [Stackoverflow -- Understanding Python Decorators](http://stackoverflow.com/questions/739654/understanding-python-decorators)
* [IBM -- Charming Python: Decorators make magic easy](http://www.ibm.com/developerworks/linux/library/l-cpdecor.html)
* [Artima -- Decorators I](http://www.artima.com/weblogs/viewpost.jsp?thread=240808)
* [Artima -- Decorators II](http://www.artima.com/weblogs/viewpost.jsp?thread=240845)
* [Artima -- Decorators III](http://www.artima.com/weblogs/viewpost.jsp?thread=241209)
* [Siafoo -- Python Decorators Don't Have to be (that) Scary](http://www.siafoo.net/article/68)
* [Valued Lessons -- Easy Python Decorators with the decorator decorator](http://www.valuedlessons.com/2008/11/easy-python-decorators-with-decorator.html)
* [Kent's Korner -- Decorators](http://personalpages.tds.net/~kent37/kk/00001.html)
* [Elf Sternberg -- Python: Decorators With Arguments (with bonus Django goodness)](http://www.elfsternberg.com/2009/11/20/python-decorators-with-arguments-with-bonus-django-goodness/)
* [Michele Simionato -- The decorator module](http://micheles.googlecode.com/hg/decorator/documentation.html)
* [The Usware Blog -- Understanding decorators](http://uswaretech.com/blog/2009/06/understanding-decorators/)
* [Gawel.org -- Les décorateurs Python](http://www.gawel.org/howtos/python-decorators)

## Conclusion

Les décorateurs sont une fonctionnalité très puissante et très utilisée du
langage Python. Python, lui-même, en propose de nombreux. Nous n'avons
qu'abordé `functools.wraps`, mais il en existe beaucoup d'autres que vous
rencontrerez certainement un jour dans vos projets. Cet article n'est qu'une
simple introduction tant les possibilités offertes sont larges. Ils sont un
point fort du langage, avec sa syntaxe et son écosystème. Ne vous en privez
pas. À vos décorateurs !


text:
require 'wraith'
require 'image_size'
require 'parallel'

class Wraith::CropImages
  attr_reader :wraith

  def initialize(config)
    @wraith = Wraith::Wraith.new(config)
  end

  def crop_images
    files = Dir.glob("#{wraith.directory}/*/*.png").sort

    Parallel.each(files.each_slice(2), in_processes: Parallel.processor_count) do |base, compare|
      puts 'cropping images'

      width          = image_dimensions(base)[0]
      base_height    = image_dimensions(base)[1]
      compare_height = image_dimensions(compare)[1]

      if base_height > compare_height
        image_to_crop     = compare
        height_to_crop_to = base_height
      else
        image_to_crop     = base
        height_to_crop_to = compare_height
      end

      crop_task(image_to_crop, height_to_crop_to, width)
    end
  end

  def crop_task(crop, height, width)
    `convert #{crop} -background none -extent #{width}x#{height} #{crop}`
  end

  def image_dimensions(image)
    ImageSize.new(File.open(image, 'rb').read).size
  end
end


text:
// ==UserScript==
// @name        Goto Location from Breadcrumbs
// @namespace   Violentmonkey Scripts
// @match       http://*/WebUI/item.aspx
// @match       https://*/WebUI/item.aspx
// @grant       none
// @version     0.16
// @author      Kunal Shetye
// ==/UserScript==

unsafeWindow.gotoLocation = {};
unsafeWindow.gotoLocation.organizationalItems = [];

jQuery(window).on('load',function(){
  waitForTridion();
});

function waitForTridion(){
    if(typeof $display !== "undefined" || typeof $evt !== "undefined"){
      $evt.addEventHandler($display, "start", displayStart);
    }
    else{
      setTimeout(waitForTridion, 250);
    }
}

function displayStart(){
  if($display.getView().properties.addressBarInitialized === true){
    prepTheBreadcrumbs();
  }
  else{
      setTimeout(displayStart, 250);
  }
}

function loadOrganizationalItems(orgItem){
   if(!orgItem.isLoaded()){
      $evt.addEventHandler(orgItem,"load",function(){
        unsafeWindow.gotoLocation.organizationalItems.push(orgItem.getId());
        if(!orgItem.getId().endsWith("-1")) {
          loadOrganizationalItems(orgItem.getOrganizationalItem());
        }
      });
      orgItem.load();
  }
  else{
    unsafeWindow.gotoLocation.organizationalItems.push(orgItem.getId());
    if(!orgItem.getId().endsWith("-1")) {
      loadOrganizationalItems(orgItem.getOrganizationalItem());
    }
  }
}

function prepTheBreadcrumbs() {
    jQuery.each(jQuery("#ItemAddressBar .addressbaritem"), function (i, v){
        var cmd = "javascript:window.gotoLocation.linkWasClicked(" + i + ");";
        var elementHtml = jQuery(v).html();
        jQuery(v).html(''+ elementHtml +'');
    });
}

unsafeWindow.gotoLocation.linkWasClicked = function(i){
  if(unsafeWindow.gotoLocation.organizationalItems.length === 0){
    loadOrganizationalItems($display.getItem().getOrganizationalItem());
    unsafeWindow.gotoLocation.organizationalItems.reverse();
  }
  s = new Tridion.Web.UI.Editors.Base.Selection();
  s.addItem(unsafeWindow.gotoLocation.organizationalItems[i]);
  $cme.getCommand('Goto')._execute(s);
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd">

<meta name="generator" content="JDiff v1.0.9">

<meta name="description" content="JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.">
<meta name="keywords" content="diff, jdiff, javadiff, java diff, java difference, API difference, difference between two APIs, API diff, Javadoc, doclet">
<TITLE>
API Differences between pig 0.3.1 and pig 0.7.0
</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="../stylesheet-jdiff.css" TITLE="Style">

       <tt>pig 0.7.0</tt>
        Overview
        Package
        Class
       Statistics
       Help

  Generated by
JDiff

  FRAMES
   NO FRAMES
   DETAIL:
REMOVED |
ADDED |
CHANGED

API Differences

Between pig 0.3.1 and pig 0.7.0

  Removed Packages

  <nobr><tt>org.apache.pig.backend.
local.datastorage</tt></nobr>

  <nobr><tt>org.apache.pig.backend.
local.executionengine</tt></nobr>

  <nobr><tt>org.apache.pig.backend.
local.executionengine.physicalLayer</tt></nobr>

  <nobr><tt>org.apache.pig.backend.
local.executionengine.physicalLayer.counters</tt></nobr>

  <nobr><tt>org.apache.pig.backend.
local.executionengine.physicalLayer.relationalOperators</tt></nobr>

  Added Packages

  <nobr><tt>org.apache.pig.experimental.
logical</tt></nobr>

  <nobr><tt>org.apache.pig.experimental.
logical.expression</tt></nobr>

  <nobr><tt>org.apache.pig.experimental.
logical.optimizer</tt></nobr>

  <nobr><tt>org.apache.pig.experimental.
logical.relational</tt></nobr>

  <nobr><tt>org.apache.pig.experimental.
logical.rules</tt></nobr>

  <nobr><tt>org.apache.pig.experimental.
plan</tt></nobr>

  <nobr><tt>org.apache.pig.experimental.
plan.optimizer</tt></nobr>

  <nobr><tt>org.apache.pig.pen.physicalOperators</tt></nobr>

  Changed Packages

  <nobr>org.apache.pig</nobr>

 Public interfaces and classes for Pig.

  <nobr>org.apache.pig.backend.
executionengine</nobr>

  <nobr>org.apache.pig.backend.
hadoop.datastorage</nobr>

  <nobr>org.apache.pig.backend.
hadoop.executionengine</nobr>

  <nobr>org.apache.pig.backend.
hadoop.executionengine.mapReduceLayer</nobr>

  <nobr>org.apache.pig.backend.
hadoop.executionengine.mapReduceLayer.partitioners</nobr>

  <nobr>org.apache.pig.backend.
hadoop.executionengine.mapReduceLayer.plans</nobr>

  <nobr>org.apache.pig.backend.
hadoop.executionengine.physicalLayer</nobr>

 Implementation of physical operators that use hadoop as the execution engine and data storage.

  <nobr>org.apache.pig.backend.
hadoop.executionengine.physicalLayer.expressionOperators</nobr>

  <nobr>org.apache.pig.backend.
hadoop.executionengine.physicalLayer.plans</nobr>

  <nobr>org.apache.pig.backend.
hadoop.executionengine.physicalLayer.relationalOperators</nobr>

  <nobr>org.apache.pig.backend.
hadoop.executionengine.physicalLayer.util</nobr>

  <nobr>org.apache.pig.backend.
hadoop.executionengine.util</nobr>

  <nobr>org.apache.pig.backend.
hadoop.hbase</nobr>

  <nobr>org.apache.pig.builtin</nobr>

  <nobr>org.apache.pig.data</nobr>

 Data types for Pig.

  <nobr>org.apache.pig.impl</nobr>

  <nobr>org.apache.pig.impl.builtin</nobr>

  <nobr>org.apache.pig.impl.io</nobr>

  <nobr>org.apache.pig.impl.logicalLayer</nobr>

 The logical operators that represent a pig script and tools for manipulating those operators.

  <nobr>org.apache.pig.impl.logicalLayer.
optimizer</nobr>

  <nobr>org.apache.pig.impl.logicalLayer.
schema</nobr>

  <nobr>org.apache.pig.impl.logicalLayer.
validators</nobr>

  <nobr>org.apache.pig.impl.plan</nobr>

  <nobr>org.apache.pig.impl.plan.
optimizer</nobr>

  <nobr>org.apache.pig.impl.streaming</nobr>

  <nobr>org.apache.pig.impl.util</nobr>

  <nobr>org.apache.pig.pen</nobr>

  <nobr>org.apache.pig.pen.util</nobr>

  <nobr>org.apache.pig.tools.grunt</nobr>

  <nobr>org.apache.pig.tools.pigstats</nobr>


text:
// Copyright 2019,2020,2021 Sony Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Include nnabla header files

/** Parametric Functions
*/

#ifndef __NBLA_PARAMETRIC_FUNCTIONS_HPP__
#define __NBLA_PARAMETRIC_FUNCTIONS_HPP__

#include <random>
#include <stdio.h>
#include <string>
#include <vector>

#include <nbla/computation_graph/computation_graph.hpp>
#include <nbla/computation_graph/function.hpp>
#include <nbla/computation_graph/variable.hpp>
#include <nbla/context.hpp>
#include <nbla/function.hpp>
#include <nbla/function/affine.hpp>
#include <nbla/function/batch_normalization.hpp>
#include <nbla/function/convolution.hpp>
#include <nbla/function/deconvolution.hpp>
#include <nbla/functions.hpp>
#include <nbla/initializer.hpp>
namespace f = nbla::functions;

namespace nbla {

CgVariablePtr make_parameter(Shape_t shape, Initializer *initializer,
                             bool need_grad);

class NBLA_API ParameterDirectory {
  typedef unordered_map<string, CgVariablePtr> dict_type;
  typedef vector<string> ordered_keys_type;

  string scope_path_;
  shared_ptr<dict_type> param_dict_;
  shared_ptr<ordered_keys_type> ordered_keys_;

  ParameterDirectory(string scope_path, shared_ptr<dict_type> param_dict,
                     shared_ptr<ordered_keys_type> ordered_keys);

public:
  // Note: the root scope is empty. No slash for consistency with Python API.
  ParameterDirectory();

public:
  ParameterDirectory operator[](string name);

  CgVariablePtr get_parameter(string name);

  vector<pair<string, VariablePtr>> get_parameters();

  CgVariablePtr get_parameter_or_create(string name, Shape_t shape,
                                        Initializer *initializer,
                                        bool need_grad);
  CgVariablePtr get_parameter_or_create(string name, CgVariablePtr variable);

  ParameterDirectory create_deep_copy();
};

namespace parametric_functions {

class NBLA_API AffineOpts {
private:
  bool with_bias_;
  bool fix_parameters_;
  Initializer *w_init_;
  Initializer *b_init_;

public:
  AffineOpts();
  AffineOpts &with_bias(bool with_bias);
  AffineOpts &fix_parameters(bool val);
  AffineOpts &w_init(Initializer *w_init);
  AffineOpts &b_init(Initializer *b_init);
  bool with_bias();
  bool fix_parameters();
  Initializer *w_init();
  Initializer *b_init();
};

class NBLA_API ConvolutionOpts {
private:
  nbla::functions::ConvolutionOpts base_;
  bool with_bias_;
  bool fix_parameters_;
  Initializer *w_init_;
  Initializer *b_init_;

public:
  ConvolutionOpts();

  ConvolutionOpts &group(int val);
  ConvolutionOpts &pad(const vector<int> &val);
  ConvolutionOpts &stride(const vector<int> &val);
  ConvolutionOpts &dilation(const vector<int> &val);
  ConvolutionOpts &channel_last(bool val);

  int group() { return base_.group(); };
  const vector<int> &pad() const { return base_.pad(); };
  const vector<int> &stride() const { return base_.stride(); };
  const vector<int> &dilation() const { return base_.dilation(); };
  bool channel_last() const { return base_.channel_last(); };

  ConvolutionOpts &with_bias(bool with_bias);
  ConvolutionOpts &fix_parameters(bool val);
  ConvolutionOpts &w_init(Initializer *w_init);
  ConvolutionOpts &b_init(Initializer *b_init);

  bool with_bias() { return with_bias_; };
  bool fix_parameters() { return fix_parameters_; };
  Initializer *w_init() { return w_init_; };
  Initializer *b_init() { return b_init_; };
};

class NBLA_API DeconvolutionOpts {
private:
  nbla::functions::DeconvolutionOpts base_;
  bool with_bias_;
  bool fix_parameters_;
  Initializer *w_init_;
  Initializer *b_init_;

public:
  DeconvolutionOpts();

  DeconvolutionOpts &group(int val);
  DeconvolutionOpts &pad(const vector<int> &val);
  DeconvolutionOpts &stride(const vector<int> &val);
  DeconvolutionOpts &dilation(const vector<int> &val);
  DeconvolutionOpts &channel_last(bool val);
  DeconvolutionOpts &output_padding(const vector<int> &val);

  int group() { return base_.group(); };
  const vector<int> &pad() const { return base_.pad(); };
  const vector<int> &stride() const { return base_.stride(); };
  const vector<int> &dilation() const { return base_.dilation(); };
  bool channel_last() const { return base_.channel_last(); };
  const vector<int> &output_padding() const { return base_.output_padding(); };

  DeconvolutionOpts &with_bias(bool with_bias);
  DeconvolutionOpts &fix_parameters(bool val);
  DeconvolutionOpts &w_init(Initializer *w_init);
  DeconvolutionOpts &b_init(Initializer *b_init);

  bool with_bias() { return with_bias_; };
  bool fix_parameters() { return fix_parameters_; };
  Initializer *w_init() { return w_init_; };
  Initializer *b_init() { return b_init_; };
};

class NBLA_API BatchNormalizationOpts {
private:
  nbla::functions::BatchNormalizationOpts base_;
  bool fix_parameters_;

public:
  BatchNormalizationOpts();

  BatchNormalizationOpts &axes(const vector<int> &val);
  BatchNormalizationOpts &decay_rate(float val);
  BatchNormalizationOpts &eps(float val);
  const vector<int> &axes() const;
  float decay_rate();
  float eps();

  BatchNormalizationOpts &fix_parameters(bool val);
  bool fix_parameters();
};

NBLA_API vector<CgVariablePtr>
affine(Context &ctx, CgVariablePtr x, int base_axis, int n_out,
       ParameterDirectory parameters, bool with_bias, bool fix_parameters,
       Initializer *w_init = nullptr, Initializer *b_init = nullptr);

NBLA_API CgVariablePtr affine(CgVariablePtr x, int base_axis, int n_out,
                              ParameterDirectory parameters,
                              AffineOpts affine_opts = AffineOpts());

NBLA_API vector<CgVariablePtr>
batch_normalization(Context &ctx, CgVariablePtr x, const vector<int> &axes,
                    float decay_rate, float eps, bool batch_stats,
                    ParameterDirectory parameters, const bool fix_parameters);

NBLA_API CgVariablePtr batch_normalization(
    CgVariablePtr x, bool batch_stat, ParameterDirectory parameters,
    BatchNormalizationOpts batch_opts = BatchNormalizationOpts());

NBLA_API vector<CgVariablePtr>
convolution(Context &ctx, CgVariablePtr x, int base_axis, int n_map_out,
            const vector<int> &kernel, const vector<int> &pad,
            const vector<int> &stride, const vector<int> &dilation, int group,
            bool channel_last, ParameterDirectory parameters, bool with_bias,
            bool fix_parameters, Initializer *w_init, Initializer *b_init);

NBLA_API CgVariablePtr
convolution(CgVariablePtr x, int base_axis, int n_map_out,
            const vector<int> &kernel, ParameterDirectory parameters,
            ConvolutionOpts conv_opts = ConvolutionOpts());

NBLA_API vector<CgVariablePtr>
deconvolution(Context &ctx, CgVariablePtr x, int base_axis, int n_map_out,
              const vector<int> &kernel, const vector<int> &pad,
              const vector<int> &stride, const vector<int> &dilation, int group,
              ParameterDirectory parameters, bool with_bias,
              bool fix_parameters, Initializer *w_init, Initializer *b_init);

NBLA_API CgVariablePtr
deconvolution(CgVariablePtr x, int base_axis, int n_map_out,
              const vector<int> &kernel, ParameterDirectory parameters,
              DeconvolutionOpts conv_opts = DeconvolutionOpts());
}
}

#endif


text:
const txt = 'Hello World!'

module.exports = {
  'Docs Pages': browser => {
    browser
      .url('http://localhost:8080/docs')
      .waitForElementVisible('body', 10000)
      .waitForElementVisible('[data-btn-modal]', 10000)
      .pause(1000)
      .click('[data-btn-modal]')
      .pause(300)
      .assert.containsText('.modal', txt)
      .click('.modal')
      .pause(300)
      .assert.elementNotPresent('.modal')

    browser
      .waitForElementVisible('[data-btn-notification]', 10000)
      .pause(1000)
      .click('[data-btn-notification]')
      .pause(300)
      .assert.containsText('.notification', txt)
      .click('[data-btn-notification]')
      .pause(300)
      .assert.elementNotPresent('.notification')

    browser
      .waitForElementVisible('[data-btn-loading]', 10000)
      .pause(1000)
      .click('[data-btn-loading]')
      .pause(100)
      .assert.elementPresent('.loading')
      .click('[data-btn-loading]')
      .pause(100)
      .assert.elementNotPresent('.loading')

    browser
      .waitForElementVisible('[data-btn-message]', 10000)
      .pause(1000)
      .click('[data-btn-message]')
      .pause(100)
      .assert.count('.message', 1)
      .click('[data-btn-message]')
      .pause(100)
      .assert.count('.message', 2)
      .click('[data-btn-message]')
      .pause(100)
      .assert.count('.message', 3)
      .click('#message-2 .message__close')
      .pause(100)
      .assert.count('.message', 2)
      .click('#message-1 .message__close')
      .pause(100)
      .assert.count('.message', 1)
      .click('#message-0 .message__close')
      .pause(100)
      .assert.count('.message', 0)
      .end()
  },

  afterEach: (browser, done) => {
    browser.updateResults()
    setTimeout(() => done(), 1000)
  }
}


text:
require "twitter"
require 'linkedin'
require 'oauth'
require 'yaml'
require 'json'
require 'fb_graph'
require 'asf-rest-adapter'
require 'nokogiri'
require 'xmlsimple'

require Rails.root.to_s + '/app/helpers/application_helper.rb'

class UsersController < ApplicationController
  def index
    if !current_user
      puts 'you are NOT logged in'
    else
      puts 'you are signed in.'
      @my_services = current_user.services.find(:all)

      get_my_feeds
    end
  end

  def get_my_feeds
    chatter = current_user.services.find(:first, :conditions => { :provider => 'forcedotcom' })
    #salesforce = current_user.services.find(:first, :conditions => { :provider => 'salesforce' })
    facebook = current_user.services.find(:first, :conditions => { :provider => 'facebook' })
    lnk = current_user.services.find(:first, :conditions => { :provider => 'linked_in' })
    twitter = current_user.services.find(:first, :conditions => { :provider => 'twitter' })

    if twitter
      begin
        do_twitter_feeds
      rescue Exception => e
        unless flash[:error].nil?
          flash[:error] << "You Twitter services has a problem: #{e.message}. Consider remove & add this service again"
        else
          flash[:error] = "You Twitter services has a problem: #{e.message}. Consider remove & add this service again"
        end
      end
    end
    if lnk
      begin
        do_linked_in_feeds
      rescue Exception => e
        unless flash[:error].nil?
          flash[:error] << "You LinkedIn services has a problem: #{e.message}. Consider remove & add this service again"
        else
          flash[:error] = "You LinkedIn services has a problem: #{e.message}. Consider remove & add this service again"
        end
      end

    end
    if chatter
      begin
        do_chatter_feeds
      rescue Exception => e
        unless flash[:error].nil?
          flash[:error] << "You Chatter services has a problem: #{e.message}. Consider remove & add this service again"
        else
          flash[:error] = "You Chatter services has a problem: #{e.message}. Consider remove & add this service again"
        end
      end

    end
    if facebook
      begin
        do_fb_feeds
      rescue Exception => e
        unless flash[:error].nil?
          flash[:error] << "You Facebook services has a problem: #{e.message}. Consider remove & add this service again"
        else
          flash[:error] = "You Facebook services has a problem: #{e.message}. Consider remove & add this service again"
        end
      end

    end

  end

  def do_chatter_feeds
    auth = current_user.services.find(:first, :conditions => { :provider => 'forcedotcom' })
    #using refresh_token to generate a new access_token
    token_refresh = auth.token_refresh
    sf_consumer_key = auth.sf_consumer_key
    sf_consumer_secret = auth.sf_consumer_secret
    ct = ApplicationHelper::chatter_client(token_refresh, sf_consumer_key, sf_consumer_secret)

    @rest_svr = ct['instance_url']
    access_token = ct['access_token']
    # Because ct['id'] is in https://login.salesforce.com/id/Org_ID/User_ID format, trim it
    # https://login.salesforce.com/id/00DA0000000XpCkMAK/00ENV['default_feed_counts'].to_sA0000000S2C7IAK
    profile_id = ct['id'].gsub(/\S+\//mi, "")
    api_version=ENV['salesforce_rest_api'] # 'v21.0'
    header = { "Authorization" => "OAuth " + access_token, "content-Type" => 'application/json' }

    #ct_user = Salesforce::Rest::User.find(profile_id)

    query = "SELECT Id, CreatedDate, CreatedBy.Name, CreatedBy.Id, FeedPost.Id, FeedPost.Body from UserFeed where parentid='#{profile_id}' order by CreatedDate Desc limit #{ENV['default_feed_counts'].to_s}"
    @chatter_feeds = Salesforce::Rest::AsfRest.run_soql(query, header, @rest_svr, api_version)['records']

  end

  def do_twitter_feeds
    # My Twitter Feed
    auth = current_user.services.find(:first, :conditions => { :provider => 'twitter' })
    token = auth.token
    token_secret = auth.token_secret
    tc = ApplicationHelper::twitter_client(token, token_secret)

    # See doc http://rubydoc.info/gems/twitter/1.2.0/Twitter/Client/Timeline
    @twitter_feeds = tc.home_timeline({:count => ENV['default_feed_counts'].to_s})
  end

  def do_linked_in_feeds
    #linked In feeds
    auth = current_user.services.find(:first, :conditions => { :provider => 'linked_in' })
    token = auth.token
    token_secret = auth.token_secret
    lnk_client = ApplicationHelper::linkedin_client(token, token_secret)
    linked_in_profile = lnk_client.profile(:fields => ['first-name', 'last-name', 'headline', 'current-share'])
    network_feeds = lnk_client.network_updates({:count => ENV['default_feed_counts'].to_s, :scope => 'self'})
    #now parsing a Nokiri document
    @linked_in_feeds = XmlSimple.xml_in(network_feeds.instance_variable_get("@doc").to_s)['updates'][0]['update']
  end

  def do_fb_feeds
    auth = current_user.services.find(:first, :conditions => { :provider => 'facebook' })
    token = auth.token
    token_secret = auth.token_secret
    fb = ApplicationHelper::fb_client(token)
    #a_user = FbGraph::User.fetch('id_please')
    @fb_feeds = fb.feed({:limit => ENV['default_feed_counts'].to_s})
  end

  def setwallpaper
    #current_user.update(:wallpaper => params[:wallpaper])
    current_user.update_attributes(:wallpaper => params[:wallpaper].to_s)
    flash[:notice] = "You wallpaper has been updated to use #{current_user.wallpaper}"
    redirect_to services_path
    return
  end

end


text:
var expect = require('chai').expect;

module.exports = (function() {

  var file;

  return {
    set: function(fileObj) {
      file = fileObj;
    },
    register: function() {
      it('should exist', function() {
        expect(file).to.be.an('object');
      });

      it('should have valid headers with sg class', function() {
        expect(file.contents.toString()).to.contain('
Title1
');
        expect(file.contents.toString()).to.contain('
Title2
');
      });

      it('should have valid paragraph with sg class', function() {
        expect(file.contents.toString()).to.contain('
Ut turkish, wings, sit to go barista half');
      });

      it('should escape code snippets and add sg class', function() {
        expect(file.contents.toString()).to.contain('
<div class="foobar>Test code snippet</div>\n
');
      });

      it('should have valid links with sg class', function() {
        expect(file.contents.toString()).to.contain('Example link');
      });
    }
  };

}());


text:
"""Helper functions to handle Mac OS information."""

import plistlib
import subprocess
import sys

class MacDiskError(Exception):
  """Module specific exception class."""

def _DictFromSubprocess(command):
  """Returns a dict based upon a subprocess call with a -plist argument.

  Args:
    command(list(str)): the command to be executed as a list.
  Returns:
    dict: dictionary from command output.
  Raises:
    MacDiskError: if the command failed to run.
  """

  try:
    task = subprocess.Popen(
        command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  except OSError as e:
    raise MacDiskError('Could not execute: {0:s}'.format(e.strerror))
  (stdout, stderr) = task.communicate()

  if task.returncode != 0:
    raise MacDiskError(
        'Error running command: {0:s}, stderr: {1:s}' .format(
            ' '.join(command), stderr))

  try:
    return plistlib.loads(stdout)
  except Exception:
    raise MacDiskError(
        'Error creating plist from output: {0:s}'.format(stdout))

def _DictFromDiskutilInfo(deviceid):
  """Calls diskutil info for a specific device ID.

  Args:
    deviceid(string): a given device id for a disk like object.
  Returns:
    dict: resulting plist output.
  Raises:
    MacDiskError: if deviceid is invalid.
  """
  command = ['/usr/sbin/diskutil', 'info', '-plist', deviceid]
  return _DictFromSubprocess(command)

def _DictFromDiskutilList():
  """Calls diskutil list -plist and returns as dict.

  Returns:
    dict: resulting plist output
  """

  command = ['/usr/sbin/diskutil', 'list', '-plist']
  return _DictFromSubprocess(command)

def WholeDisks():
  """Returns a list of all disk objects that are whole disks."""
  wholedisks = []
  try:
    diskutil_dict = _DictFromDiskutilList()
    for deviceid in diskutil_dict['WholeDisks']:
      wholedisks.append(Disk(deviceid))
  except KeyError:
    raise MacDiskError('Unable to list all partitions.')
  return wholedisks

class Disk(object):
  """Represents a Mac disk object.

  Note that this also is used for currently mounted disk images as they
  really are just 'disks'. Mostly. Can take device ids of the form 'disk1' or
  of the form '/dev/disk1'.
  """

  def __init__(self, deviceid):
    """Initializes a MacDisk object.

    Args:
      deviceid(str): Name (or path) to a disk
    """
    if deviceid.startswith('/dev/'):
      deviceid = deviceid.replace('/dev/', '', 1)
    self.deviceid = deviceid
    self.Refresh()

  def Refresh(self):
    """Builds a list of convenience attributes for direct querying."""

    self._attributes = _DictFromDiskutilInfo(self.deviceid)
    # These are the keys we are interested in
    keys = ['Internal', 'DeviceIdentifier', 'BusProtocol', 'VirtualOrPhysical',
            'DeviceIdentifier', 'TotalSize']

    for key in keys:
      try:
        attribute = key.lower().replace(' ', '')
        setattr(self, attribute, self._attributes[key])
      except KeyError:  # not all objects have all these attributes
        pass


text:
<?php

namespace InCommon\Tests\Api;

use InCommon\InCommon;

class CertsTest extends \PHPUnit_Framework_TestCase
{
    /** @test */
    public function it_stubbin()
    {

    }
}


text:
package org.sakaiproject.tool.assessment.ui.listener.author;

import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;

import org.sakaiproject.event.cover.EventTrackingService;
import org.sakaiproject.tool.assessment.facade.AgentFacade;
import org.sakaiproject.tool.assessment.facade.AssessmentFacade;
import org.sakaiproject.tool.assessment.services.assessment.AssessmentService;
import org.sakaiproject.tool.assessment.ui.bean.author.AssessmentBean;
import org.sakaiproject.tool.assessment.ui.bean.author.SectionBean;
import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil;

/**
 *
Title: Samigo

 *
Description: Sakai Assessment Manager

 * @author Ed Smiley
 * @version $Id$
 */

public class RemovePartListener implements ActionListener
{
  //private static Log log = LogFactory.getLog(RemovePartListener.class);

  public RemovePartListener()
  {
  }

  public void processAction(ActionEvent ae) throws AbortProcessingException
  {
    AssessmentBean assessmentBean = (AssessmentBean) ContextUtil.lookupBean(
        "assessmentBean");
    SectionBean sectionBean = (SectionBean) ContextUtil.lookupBean(
        "sectionBean");

    // #1. get all the info need from bean
    String sectionId = sectionBean.getSectionId();
    String destSectionId = sectionBean.getDestSectionId();
    String removeAllQuestions = sectionBean.getRemoveAllQuestions();

    // #2 - check if we are removing all question or we
    // need to move question to another part
    AssessmentService assessmentService = new AssessmentService();
    //log.info("** removeAll Question="+removeAllQuestions);
    if (!("1").equals(removeAllQuestions)){
      // move questions to destinated Section when removing a section
      if (destSectionId == null || ("").equals(destSectionId)){
        destSectionId = assessmentBean.getFirstSectionId();
      }
      assessmentService.moveAllItems(sectionId,destSectionId);
    }
    assessmentService.removeSection(sectionId);
    EventTrackingService.post(EventTrackingService.newEvent("sam.assessment.revise", "siteId=" + AgentFacade.getCurrentSiteId() + ", removed sectionId=" + sectionId, true));

    // #2 - goto editAssessment.jsp, so reset assessmentBean
    //log.info("** assessmentId in RemovePartListener ="+assessmentBean.getAssessmentId());
    AssessmentFacade assessment = assessmentService.getAssessment(
        assessmentBean.getAssessmentId());
    assessmentBean.setAssessment(assessment);

  }

}


text:
package SmartTanker;

import uk.ac.nott.cs.g54dia.library.Station;
import uk.ac.nott.cs.g54dia.library.Task;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by JasonChen on 2/16/15.
 */
public class TaskSys {
    Map<Task, MemPoint> task_list = new HashMap<Task, MemPoint>();

    public Task scanTaskList(MemPoint p) {
        Task t = null;
        int min_cost = 100;
        int score;
        int cost;
        Iterator it = this.task_list.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pairs = (Map.Entry)it.next();
            Task t_r = (Task) pairs.getKey();
            MemPoint t_p = (MemPoint) pairs.getValue();
            if (t_r.isComplete()) {
                it.remove();
            } else if (p.equals(t_p)) {
                // at this point
                t = t_r;
                break;
            } else {
                cost = t_p.calcDistance(p);
                score = t_r.getRequired();
                // if can get more score by spend cost
                if (cost - score < min_cost) {
                    min_cost = cost;
                    t = t_r;
                }
            }
        }
        return t;
    }

    public void appendTask(MemPoint p, MemMap map) {
        Station s = ((Station) map.getCell(p));
        if (s != null) {
            Task t = s.getTask();
            if (t != null) {
                Iterator it = this.task_list.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry pairs = (Map.Entry) it.next();
                    Task t_r = (Task) pairs.getKey();
                    if (t_r == t) {
                        it.remove();
                    }
                }
                this.task_list.put(t, (MemPoint) p.clone());
            }
        }
    }

    public MemPoint getPoint(Task t) {
        Iterator it = this.task_list.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pairs = (Map.Entry)it.next();
            Task t_r = (Task) pairs.getKey();
            if (t_r == t) {
                return (MemPoint) pairs.getValue();
            }
        }
        return null;
    }
}


text:
<?php

Class User_model extends MY_model{

    protected $table_name = 'users';

    public function getUser($username,$password){
        return $this->db->where('username', $username)
                        ->where('password', $password)
                        ->get($this->table_name)
                        ->row();
    }
}
?>


text:
@interface AgendaSecondDayController ()
@property NSArray *sessions;
@end

@implementation AgendaSecondDayController

- (void)viewDidLoad {
    [super viewDidLoad];

    UIBarButtonItem *mBtn=[[UIBarButtonItem alloc] init];
    mBtn.target = self.revealViewController;
    mBtn.action = @selector(revealToggle:);
    mBtn.image=[UIImage imageNamed:@"menuBar.png"];
    mBtn.tintColor=[UIColor orangeColor];
    self.tabBarController.navigationItem.leftBarButtonItem=mBtn;
    _sessions=[[JETSAgendaModel new] getDaySessions:2];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"CellSession";
    SessionCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    JETSSession *sess = [_sessions  objectAtIndex:indexPath.row];
    [cell.sessionName renderHTML:sess.name];
    cell.sessionImage.image=[UIImage imageNamed:[sess.sessionType stringByAppendingString:@".png"]];
    cell.sessionPlace.text=sess.location;
    cell.sessionTime.text=[[DateHelper new] difrenceBetweenStartDate:sess.startDate EndDate:sess.endDate];
    cell.sessionDay.text=[[DateHelper new] getDaynmber:sess.startDate];
    return cell;
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return  _sessions.count;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    SingleSessionController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"SingleSession"];
    vc.session=[_sessions  objectAtIndex:indexPath.row];
    [self.navigationController pushViewController:vc animated:YES];
}

@end


text:
namespace blink {

// An helper function for the two create() methods. The return value is an
// indicate of whether the create() should return nullptr or not.
static bool ShouldCreateContext(WebGraphicsContext3DProvider* context_provider,
                                CanvasRenderingContextHost* host) {
  if (!context_provider) {
    host->HostDispatchEvent(
        WebGLContextEvent::Create(event_type_names::kWebglcontextcreationerror,
                                  "Failed to create a WebGL2 context."));
    return false;
  }

  gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
  std::unique_ptr<Extensions3DUtil> extensions_util =
      Extensions3DUtil::Create(gl);
  if (!extensions_util)
    return false;
  if (extensions_util->SupportsExtension("GL_EXT_debug_marker")) {
    String context_label(
        String::Format("WebGL2RenderingContext-%p", context_provider));
    gl->PushGroupMarkerEXT(0, context_label.Ascii().c_str());
  }
  return true;
}

CanvasRenderingContext* WebGL2RenderingContext::Factory::Create(
    CanvasRenderingContextHost* host,
    const CanvasContextCreationAttributesCore& attrs) {
  // Create a copy of attrs so flags can be modified if needed before passing
  // into the WebGL2RenderingContext constructor.
  CanvasContextCreationAttributesCore attribs = attrs;

  // The xr_compatible attribute needs to be handled before creating the context
  // because the GPU process may potentially be restarted in order to be XR
  // compatible. This scenario occurs if the GPU process is not using the GPU
  // that the VR headset is plugged into. If the GPU process is restarted, the
  // WebGraphicsContext3DProvider must be created using the new one.
  if (attribs.xr_compatible &&
      !WebGLRenderingContextBase::MakeXrCompatibleSync(host)) {
    // If xr compatibility is requested and we can't be xr compatible, return a
    // context with the flag set to false.
    attribs.xr_compatible = false;
  }

  Platform::GraphicsInfo graphics_info;
  std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
      CreateWebGraphicsContext3DProvider(
          host, attribs, Platform::kWebGL2ContextType, &graphics_info));
  if (!ShouldCreateContext(context_provider.get(), host))
    return nullptr;
  WebGL2RenderingContext* rendering_context =
      MakeGarbageCollected<WebGL2RenderingContext>(
          host, std::move(context_provider), graphics_info, attribs);

  if (!rendering_context->GetDrawingBuffer()) {
    host->HostDispatchEvent(
        WebGLContextEvent::Create(event_type_names::kWebglcontextcreationerror,
                                  "Could not create a WebGL2 context."));
    // We must dispose immediately so that when rendering_context is
    // garbage-collected, it will not interfere with a subsequently created
    // rendering context.
    rendering_context->Dispose();
    return nullptr;
  }

  rendering_context->InitializeNewContext();
  rendering_context->RegisterContextExtensions();
  return rendering_context;
}

void WebGL2RenderingContext::Factory::OnError(HTMLCanvasElement* canvas,
                                              const String& error) {
  canvas->DispatchEvent(*WebGLContextEvent::Create(
      event_type_names::kWebglcontextcreationerror, error));
}

WebGL2RenderingContext::WebGL2RenderingContext(
    CanvasRenderingContextHost* host,
    std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
    const Platform::GraphicsInfo& graphics_info,
    const CanvasContextCreationAttributesCore& requested_attributes)
    : WebGL2RenderingContextBase(host,
                                 std::move(context_provider),
                                 graphics_info,
                                 requested_attributes,
                                 Platform::kWebGL2ContextType) {}

V8RenderingContext* WebGL2RenderingContext::AsV8RenderingContext() {
  return MakeGarbageCollected<V8RenderingContext>(this);
}

V8OffscreenRenderingContext*
WebGL2RenderingContext::AsV8OffscreenRenderingContext() {
  return MakeGarbageCollected<V8OffscreenRenderingContext>(this);
}

ImageBitmap* WebGL2RenderingContext::TransferToImageBitmap(
    ScriptState* script_state) {
  return TransferToImageBitmapBase(script_state);
}

void WebGL2RenderingContext::RegisterContextExtensions() {
  // Register extensions.
  RegisterExtension(ext_color_buffer_float_);
  RegisterExtension(ext_color_buffer_half_float_);
  RegisterExtension(
      ext_disjoint_timer_query_web_gl2_,
      TimerQueryExtensionsEnabled() ? kApprovedExtension : kDeveloperExtension);
  RegisterExtension(ext_float_blend_);
  RegisterExtension(ext_texture_compression_bptc_);
  RegisterExtension(ext_texture_compression_rgtc_);
  RegisterExtension(ext_texture_filter_anisotropic_);
  RegisterExtension(ext_texture_norm16_);
  RegisterExtension(khr_parallel_shader_compile_);
  RegisterExtension(oes_draw_buffers_indexed_);
  RegisterExtension(oes_texture_float_linear_);
  RegisterExtension(webgl_compressed_texture_astc_);
  RegisterExtension(webgl_compressed_texture_etc_);
  RegisterExtension(webgl_compressed_texture_etc1_);
  RegisterExtension(webgl_compressed_texture_pvrtc_);
  RegisterExtension(webgl_compressed_texture_s3tc_);
  RegisterExtension(webgl_compressed_texture_s3tc_srgb_);
  RegisterExtension(webgl_debug_renderer_info_);
  RegisterExtension(webgl_debug_shaders_);
  RegisterExtension(webgl_draw_instanced_base_vertex_base_instance_,
                    kDraftExtension);
  RegisterExtension(webgl_lose_context_);
  RegisterExtension(webgl_multi_draw_);
  RegisterExtension(webgl_multi_draw_instanced_base_vertex_base_instance_,
                    kDraftExtension);
  RegisterExtension(webgl_video_texture_, kDraftExtension);
  RegisterExtension(webgl_webcodecs_video_frame_, kDraftExtension);
  RegisterExtension(ovr_multiview2_);
}

void WebGL2RenderingContext::Trace(Visitor* visitor) const {
  visitor->Trace(ext_color_buffer_float_);
  visitor->Trace(ext_color_buffer_half_float_);
  visitor->Trace(ext_disjoint_timer_query_web_gl2_);
  visitor->Trace(ext_float_blend_);
  visitor->Trace(ext_texture_compression_bptc_);
  visitor->Trace(ext_texture_compression_rgtc_);
  visitor->Trace(ext_texture_filter_anisotropic_);
  visitor->Trace(ext_texture_norm16_);
  visitor->Trace(khr_parallel_shader_compile_);
  visitor->Trace(oes_draw_buffers_indexed_);
  visitor->Trace(oes_texture_float_linear_);
  visitor->Trace(ovr_multiview2_);
  visitor->Trace(webgl_compressed_texture_astc_);
  visitor->Trace(webgl_compressed_texture_etc_);
  visitor->Trace(webgl_compressed_texture_etc1_);
  visitor->Trace(webgl_compressed_texture_pvrtc_);
  visitor->Trace(webgl_compressed_texture_s3tc_);
  visitor->Trace(webgl_compressed_texture_s3tc_srgb_);
  visitor->Trace(webgl_debug_renderer_info_);
  visitor->Trace(webgl_debug_shaders_);
  visitor->Trace(webgl_draw_instanced_base_vertex_base_instance_);
  visitor->Trace(webgl_lose_context_);
  visitor->Trace(webgl_multi_draw_);
  visitor->Trace(webgl_multi_draw_instanced_base_vertex_base_instance_);
  visitor->Trace(webgl_video_texture_);
  visitor->Trace(webgl_webcodecs_video_frame_);
  WebGL2RenderingContextBase::Trace(visitor);
}

}  // namespace blink


text:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder
			by default -->
		<encoder>
			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
		</encoder>
	</appender>

	<appender name="ROLLINGFILE"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<file>logs/coarapp.log</file>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<!-- daily rollover -->
			<fileNamePattern>logs/coarapp.%d{yyyy-MM-dd}.log</fileNamePattern>

			<!-- keep 30 days' worth of history -->
			<maxHistory>30</maxHistory>
		</rollingPolicy>

		<encoder>
			<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
		</encoder>
	</appender>

	<!-- logger name="nl.knaw.dans.coar.walk.CoordinateDetector" level="debug"/-->

	<root level="info">
		<!-- appender-ref ref="STDOUT" /-->
		<appender-ref ref="ROLLINGFILE" />
	</root>
</configuration>


text:
<?php defined('T') OR die(); ?>

Welcome!

Thanks for trying out the 1kb MVC Framework!


text:
"""
Pipeline for flexible modeling and extration of slitless spectroscopy
"""
#__version__ = "0.1.1.dev"
from .version import __version__

import os

## Will get ImportError: No module named disperse" if imported in the repo directory
# if os.path.exists('README.rst') & os.path.exists('LICENSE.txt'):
#     print("""
# Warning: `import grizli` will fail if the working directory is the place
# where the code repository was cloned and compiled!
# """)

# Module imports
# from . import utils_c
# from . import utils
# from . import grismconf
# from . import model
# from . import multifit

# Test that GRIZLI system variable is set
if os.getenv('GRIZLI') is None:
    GRIZLI_PATH = os.path.join(os.path.dirname(__file__), 'data/')

    print("""
Warning: $GRIZLI system variable not set and will default to {0}.
Grizli will need to find the configuration files in $GRIZLI/CONF.
    """.format(GRIZLI_PATH))
    #GRIZLI_PATH = '/usr/local/share/grizli_home'
else:
    GRIZLI_PATH = os.getenv('GRIZLI')

try:
    import sep
except:
    print("""
Couldn't `import sep`.  SExtractor replaced with SEP
in April 2018.  Install with `pip install sep`.
""")

try:
    import tristars
except:
    print("""
Couldn't `import tristars`.  Get it from https://github.com/gbrammer/tristars to enable improved blind astrometric matching with triangle asterisms.
""")


text:
Slicer the packed cocos2d resources(with tool TexturePacker) into the original ones. Can't slice the files zwoptex packed."

## Installation

First. Install the [Imagemagick](http://www.imagemagick.org/script/index.php) command line tools.
Then

Add this line to your application's Gemfile:

    gem 'cocoslicer'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install cocoslicer

## Usage

cocoslicer packed.plist

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request