问:
Google API Won't Let me Retrieve Gmail Messages Using OAuth in PHP (returns 401 - Login Required)
I'm at my wit's end on this.  I have the OAuth setup and working (i.e. I'm able to retrieve access/refresh tokens after authorizing), but when I try to connect to my Gmail inbox, Google just spits back a 401 with a JSON saying that login is required.

I'm using the beta google-api-php-client library and I haven't been able to find any non-deprecated solutions to this.  What's weird is that I was able to retrieve a message on the very first test, but after that (without any code changes) it started returning a 401 instead and it's driving me bonkers.

Here's the relevant code in question:

```<code><?php

public function __construct( $autoAuth = FALSE )
{
    require_once( 'scripts/gmail/config.class.php' );
    require_once( 'scripts/gmail/google-api-php-client/vendor/autoload.php' );

    $this->appName = gmail_config::$appName;
    $this->clientId = gmail_config::$clientId;
    $this->clientSecret = gmail_config::$clientSecret;

    $this->client = new Google_Client();

    // Using the JSON also returned a 401 so I tried it without; no change.
    //$this->client->setAuthConfig( 'scripts/gmail/gmail_client_id.json' );
    $this->client->setClientId( gmail_config::$clientId );
    $this->client->setClientSecret( gmail_config::$clientSecret );

    // On user auth screen, it keeps saying I'm only requesting "offline access".  Any idea why?
    $this->client->addScope( 'https://mail.google.com/' );
    $this->client->addScope( 'https://www.googleapis.com/auth/gmail.compose' );

    $this->client->setRedirectUri( '(redacted)' );

    // Required for generating a refresh token.  --Kris
    $this->client->setAccessType( 'offline' );
    $this->client->setApprovalPrompt( 'force' );

    $this->authURL = $this->client->createAuthUrl();

    $this->SQLInit();

    if ( $autoAuth === TRUE )
    {
        if ( !( $this->auth() ) )
        {
            print 'User authorization required : ' . $this->authURL;
        }
    }
}

public function auth()
{
    $res = $this->SQLQuery( 'SELECT * FROM oauth_tokens WHERE service = ?', array( 'gmail' ) );

    if ( !empty( $res ) && !empty( $res['accessToken'] ) && !empty( $res['refreshToken'] ) && !empty( $res['issued'] ) && !empty( $res['lastRefresh'] ) )
    {
        $this->accessToken = json_decode( $res['accessToken'], TRUE );
        $this->refreshToken = $res['refreshToken'];
        $this->tokenIssued = strtotime( $res['issued'] );
        $this->lastTokenRefresh = strtotime( $res['lastRefresh'] );

        if ( (time() - $this->lastTokenRefresh) >= 3600 )
        {
            $this->refreshToken();
        }

        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

public function refreshToken()
{
    $this->client->refreshToken( $this->refreshToken );
    $this->accessToken = $this->client->getAccessToken();

    $this->SQLQuery( 'DELETE FROM oauth_tokens WHERE service = ?', array( 'gmail' ), SQL_RETURN_AFFECTEDROWS );

    $this->SQLQuery( 'INSERT INTO oauth_tokens ( service, accessToken, refreshToken, lastRefresh ) VALUES ( ?, ?, ?, NOW() )',
            array( 'gmail', json_encode( $this->accessToken ), $this->accessToken['refresh_token'] ),
            SQL_RETURN_AFFECTEDROWS );
}

public function getMessagesTest( $limit = 5 )
{
    $service = new Google_Service_Gmail( $this->client );

    $optParams = [];
    $optParams['maxResults'] = $limit; // Return Only $limit Messages
    $optParams['labelIds'] = 'INBOX'; // Only show messages in Inbox

    $messages = $service->users_messages->listUsersMessages( 'me', $optParams ); // <-- THIS IS WHERE IT'S FAILING!
    $list = $messages->getMessages();

    $res = array();
    foreach ( $list as $key => $email )
    {
        $messageId = $email->getId(); // Grab Message

        $optParamsGet = [];
        $optParamsGet['format'] = 'full'; // Display message in payload

        $message = $service->users_messages->get( 'me', $messageId, $optParamsGet );
        $messagePayload = $message->getPayload();

        $headers = $message->getPayload()->getHeaders();
        $parts = $message->getPayload()->getParts();

        $body = $parts[0]['body'];
        $rawData = $body->data;
        $sanitizedData = strtr( $rawData, '-_', '+/' );
        $decodedMessage = base64_decode( $sanitizedData );

        $res[$key] = array();
        $res[$key]['message'] = $decodedMessage;
        $res[$key]['parts'] = $parts;
    }

    return $res;
}
</code>```

In case it helps, here's where the tokens are being stored from the redirectUri endpoint:

```<code>    <?php

    try
    {
        $gmail = new gmail();
        $token = $gmail->client->fetchAccessTokenWithAuthCode( $params[1]['code'] );

        $sql->query( 'DELETE FROM oauth_tokens WHERE service = ?', array( 'gmail' ), SQL_RETURN_AFFECTEDROWS );
        $sql->query( 'INSERT INTO oauth_tokens ( service, accessToken, refreshToken, lastRefresh ) VALUES ( ?, ?, ?, NOW() )', array( 'gmail', json_encode( $token ), $token['refresh_token'] ) );
    }
    catch ( Exception $e )
    {
        return array( 'status' => 500, 'error' => 'SQL error on insert : ' . $e->getMessage() );
    }
</code>```

I've been Googling this for hours and nothing I've tried has had any effect.  I did try revisiting the authURL to refresh the tokens/etc but that didn't work.

I'd prefer a simple fix (i.e. maybe just some required thing that I'm missing?) over refactoring everything to use something else.  That said, I'm stumped.  Does anybody know what I'm doing wrong here?  If you need additional code/information, please let me know and I'll include it.

Thanks for your help!  This is blocking the whole project now so hopefully one of you will see what it is I'm missing....

EDIT

I added a var_dump( $this->client ) to getMessagesTest() as one of you suggested.  Here's the redacted output:

```<code>object(Google_Client)#10 (8) {
  ["auth":"Google_Client":private]=>
  object(Google\Auth\OAuth2)#11 (24) {
    ["authorizationUri":"Google\Auth\OAuth2":private]=>
    object(GuzzleHttp\Psr7\Uri)#12 (7) {
      ["scheme":"GuzzleHttp\Psr7\Uri":private]=>
      string(5) "https"
      ["userInfo":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
      ["host":"GuzzleHttp\Psr7\Uri":private]=>
      string(19) "accounts.google.com"
      ["port":"GuzzleHttp\Psr7\Uri":private]=>
      NULL
      ["path":"GuzzleHttp\Psr7\Uri":private]=>
      string(14) "/o/oauth2/auth"
      ["query":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
      ["fragment":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
    }
    ["tokenCredentialUri":"Google\Auth\OAuth2":private]=>
    object(GuzzleHttp\Psr7\Uri)#13 (7) {
      ["scheme":"GuzzleHttp\Psr7\Uri":private]=>
      string(5) "https"
      ["userInfo":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
      ["host":"GuzzleHttp\Psr7\Uri":private]=>
      string(18) "www.googleapis.com"
      ["port":"GuzzleHttp\Psr7\Uri":private]=>
      NULL
      ["path":"GuzzleHttp\Psr7\Uri":private]=>
      string(16) "/oauth2/v4/token"
      ["query":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
      ["fragment":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
    }
    ["redirectUri":"Google\Auth\OAuth2":private]=>
    string(47) "(my redirect URL)"
    ["clientId":"Google\Auth\OAuth2":private]=>
    string(72) "(my clientId).apps.googleusercontent.com"
    ["clientSecret":"Google\Auth\OAuth2":private]=>
    string(24) "(my client secret)"
    ["username":"Google\Auth\OAuth2":private]=>
    NULL
    ["password":"Google\Auth\OAuth2":private]=>
    NULL
    ["scope":"Google\Auth\OAuth2":private]=>
    NULL
    ["state":"Google\Auth\OAuth2":private]=>
    NULL
    ["code":"Google\Auth\OAuth2":private]=>
    NULL
    ["issuer":"Google\Auth\OAuth2":private]=>
    string(72) "(my clientId).apps.googleusercontent.com"
    ["audience":"Google\Auth\OAuth2":private]=>
    NULL
    ["sub":"Google\Auth\OAuth2":private]=>
    NULL
    ["expiry":"Google\Auth\OAuth2":private]=>
    int(3600)
    ["signingKey":"Google\Auth\OAuth2":private]=>
    NULL
    ["signingAlgorithm":"Google\Auth\OAuth2":private]=>
    NULL
    ["refreshToken":"Google\Auth\OAuth2":private]=>
    NULL
    ["accessToken":"Google\Auth\OAuth2":private]=>
    NULL
    ["idToken":"Google\Auth\OAuth2":private]=>
    NULL
    ["expiresIn":"Google\Auth\OAuth2":private]=>
    NULL
    ["expiresAt":"Google\Auth\OAuth2":private]=>
    NULL
    ["issuedAt":"Google\Auth\OAuth2":private]=>
    NULL
    ["grantType":"Google\Auth\OAuth2":private]=>
    NULL
    ["extensionParams":"Google\Auth\OAuth2":private]=>
    array(0) {
    }
  }
  ["http":"Google_Client":private]=>
  NULL
  ["cache":"Google_Client":private]=>
  NULL
  ["token":"Google_Client":private]=>
  NULL
  ["config":"Google_Client":private]=>
  array(23) {
    ["application_name"]=>
    string(0) ""
    ["base_path"]=>
    string(26) "https://www.googleapis.com"
    ["client_id"]=>
    string(72) "(my clientId).apps.googleusercontent.com"
    ["client_secret"]=>
    string(24) "(my client secret)"
    ["redirect_uri"]=>
    string(47) "(my redirect URL)"
    ["state"]=>
    NULL
    ["developer_key"]=>
    string(0) ""
    ["use_application_default_credentials"]=>
    bool(false)
    ["signing_key"]=>
    NULL
    ["signing_algorithm"]=>
    NULL
    ["subject"]=>
    NULL
    ["hd"]=>
    string(0) ""
    ["prompt"]=>
    string(0) ""
    ["openid.realm"]=>
    string(0) ""
    ["include_granted_scopes"]=>
    NULL
    ["login_hint"]=>
    string(0) ""
    ["request_visible_actions"]=>
    string(0) ""
    ["access_type"]=>
    string(7) "offline"
    ["approval_prompt"]=>
    string(5) "force"
    ["retry"]=>
    array(0) {
    }
    ["cache_config"]=>
    array(0) {
    }
    ["token_callback"]=>
    NULL
    ["jwt"]=>
    NULL
  }
  ["logger":"Google_Client":private]=>
  NULL
  ["deferExecution":"Google_Client":private]=>
  bool(false)
  ["requestedScopes":protected]=>
  array(2) {
    [0]=>
    string(24) "https://mail.google.com/"
    [1]=>
    string(45) "https://www.googleapis.com/auth/gmail.compose"
  }
}
</code>```

Thanks again for your help!

答:
So it looks like the problem was that the access token had expired and my refreshToken() function was rigged to manually check for expiration by comparing the current time to when it was stored in the database.  But since I'm using an idempotent REST API, I had set it up to delete and re-insert the tokens whenever user authorization occurs (i.e. by following the authURL in a browser).  As a result, the 'issued' timestamp was being reset whenever I impatiently went back to the authURL to try to obtain a new token, not realizing that it was just giving me the same expired access token as before each and every time.

Apparently, you have to use the refresh token to get a new one; i.e. even starting over with the authURL won't cut it.  I put it all together when I noticed that the client has a built-in isAccessTokenExpired() function, so I modified my ifcheck to use that and everything works now.

TL;DR:  My refresh code wasn't getting called because I incorrectly assumed that the access token is automatically refreshed when you have the user revisit the authURL.

Body:
I'm at my wit's end on this.  I have the OAuth setup and working (i.e. I'm able to retrieve access/refresh tokens after authorizing), but when I try to connect to my Gmail inbox, Google just spits back a 401 with a JSON saying that login is required.

I'm using the beta google-api-php-client library and I haven't been able to find any non-deprecated solutions to this.  What's weird is that I was able to retrieve a message on the very first test, but after that (without any code changes) it started returning a 401 instead and it's driving me bonkers.

Here's the relevant code in question:

<?php

public function __construct( $autoAuth = FALSE )
{
    require_once( 'scripts/gmail/config.class.php' );
    require_once( 'scripts/gmail/google-api-php-client/vendor/autoload.php' );

    $this->appName = gmail_config::$appName;
    $this->clientId = gmail_config::$clientId;
    $this->clientSecret = gmail_config::$clientSecret;

    $this->client = new Google_Client();

    // Using the JSON also returned a 401 so I tried it without; no change.
    //$this->client->setAuthConfig( 'scripts/gmail/gmail_client_id.json' );
    $this->client->setClientId( gmail_config::$clientId );
    $this->client->setClientSecret( gmail_config::$clientSecret );

    // On user auth screen, it keeps saying I'm only requesting "offline access".  Any idea why?
    $this->client->addScope( 'https://mail.google.com/' );
    $this->client->addScope( 'https://www.googleapis.com/auth/gmail.compose' );

    $this->client->setRedirectUri( '(redacted)' );

    // Required for generating a refresh token.  --Kris
    $this->client->setAccessType( 'offline' );
    $this->client->setApprovalPrompt( 'force' );

    $this->authURL = $this->client->createAuthUrl();

    $this->SQLInit();

    if ( $autoAuth === TRUE )
    {
        if ( !( $this->auth() ) )
        {
            print 'User authorization required : ' . $this->authURL;
        }
    }
}

public function auth()
{
    $res = $this->SQLQuery( 'SELECT * FROM oauth_tokens WHERE service = ?', array( 'gmail' ) );

    if ( !empty( $res ) && !empty( $res['accessToken'] ) && !empty( $res['refreshToken'] ) && !empty( $res['issued'] ) && !empty( $res['lastRefresh'] ) )
    {
        $this->accessToken = json_decode( $res['accessToken'], TRUE );
        $this->refreshToken = $res['refreshToken'];
        $this->tokenIssued = strtotime( $res['issued'] );
        $this->lastTokenRefresh = strtotime( $res['lastRefresh'] );

        if ( (time() - $this->lastTokenRefresh) >= 3600 )
        {
            $this->refreshToken();
        }

        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

public function refreshToken()
{
    $this->client->refreshToken( $this->refreshToken );
    $this->accessToken = $this->client->getAccessToken();

    $this->SQLQuery( 'DELETE FROM oauth_tokens WHERE service = ?', array( 'gmail' ), SQL_RETURN_AFFECTEDROWS );

    $this->SQLQuery( 'INSERT INTO oauth_tokens ( service, accessToken, refreshToken, lastRefresh ) VALUES ( ?, ?, ?, NOW() )',
            array( 'gmail', json_encode( $this->accessToken ), $this->accessToken['refresh_token'] ),
            SQL_RETURN_AFFECTEDROWS );
}

public function getMessagesTest( $limit = 5 )
{
    $service = new Google_Service_Gmail( $this->client );

    $optParams = [];
    $optParams['maxResults'] = $limit; // Return Only $limit Messages
    $optParams['labelIds'] = 'INBOX'; // Only show messages in Inbox

    $messages = $service->users_messages->listUsersMessages( 'me', $optParams ); // <-- THIS IS WHERE IT'S FAILING!
    $list = $messages->getMessages();

    $res = array();
    foreach ( $list as $key => $email )
    {
        $messageId = $email->getId(); // Grab Message

        $optParamsGet = [];
        $optParamsGet['format'] = 'full'; // Display message in payload

        $message = $service->users_messages->get( 'me', $messageId, $optParamsGet );
        $messagePayload = $message->getPayload();

        $headers = $message->getPayload()->getHeaders();
        $parts = $message->getPayload()->getParts();

        $body = $parts[0]['body'];
        $rawData = $body->data;
        $sanitizedData = strtr( $rawData, '-_', '+/' );
        $decodedMessage = base64_decode( $sanitizedData );

        $res[$key] = array();
        $res[$key]['message'] = $decodedMessage;
        $res[$key]['parts'] = $parts;
    }

    return $res;
}

In case it helps, here's where the tokens are being stored from the redirectUri endpoint:

    <?php

    try
    {
        $gmail = new gmail();
        $token = $gmail->client->fetchAccessTokenWithAuthCode( $params[1]['code'] );

        $sql->query( 'DELETE FROM oauth_tokens WHERE service = ?', array( 'gmail' ), SQL_RETURN_AFFECTEDROWS );
        $sql->query( 'INSERT INTO oauth_tokens ( service, accessToken, refreshToken, lastRefresh ) VALUES ( ?, ?, ?, NOW() )', array( 'gmail', json_encode( $token ), $token['refresh_token'] ) );
    }
    catch ( Exception $e )
    {
        return array( 'status' => 500, 'error' => 'SQL error on insert : ' . $e->getMessage() );
    }

I've been Googling this for hours and nothing I've tried has had any effect.  I did try revisiting the authURL to refresh the tokens/etc but that didn't work.

I'd prefer a simple fix (i.e. maybe just some required thing that I'm missing?) over refactoring everything to use something else.  That said, I'm stumped.  Does anybody know what I'm doing wrong here?  If you need additional code/information, please let me know and I'll include it.

Thanks for your help!  This is blocking the whole project now so hopefully one of you will see what it is I'm missing....

EDIT

I added a var_dump( $this->client ) to getMessagesTest() as one of you suggested.  Here's the redacted output:

object(Google_Client)#10 (8) {
  ["auth":"Google_Client":private]=>
  object(Google\Auth\OAuth2)#11 (24) {
    ["authorizationUri":"Google\Auth\OAuth2":private]=>
    object(GuzzleHttp\Psr7\Uri)#12 (7) {
      ["scheme":"GuzzleHttp\Psr7\Uri":private]=>
      string(5) "https"
      ["userInfo":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
      ["host":"GuzzleHttp\Psr7\Uri":private]=>
      string(19) "accounts.google.com"
      ["port":"GuzzleHttp\Psr7\Uri":private]=>
      NULL
      ["path":"GuzzleHttp\Psr7\Uri":private]=>
      string(14) "/o/oauth2/auth"
      ["query":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
      ["fragment":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
    }
    ["tokenCredentialUri":"Google\Auth\OAuth2":private]=>
    object(GuzzleHttp\Psr7\Uri)#13 (7) {
      ["scheme":"GuzzleHttp\Psr7\Uri":private]=>
      string(5) "https"
      ["userInfo":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
      ["host":"GuzzleHttp\Psr7\Uri":private]=>
      string(18) "www.googleapis.com"
      ["port":"GuzzleHttp\Psr7\Uri":private]=>
      NULL
      ["path":"GuzzleHttp\Psr7\Uri":private]=>
      string(16) "/oauth2/v4/token"
      ["query":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
      ["fragment":"GuzzleHttp\Psr7\Uri":private]=>
      string(0) ""
    }
    ["redirectUri":"Google\Auth\OAuth2":private]=>
    string(47) "(my redirect URL)"
    ["clientId":"Google\Auth\OAuth2":private]=>
    string(72) "(my clientId).apps.googleusercontent.com"
    ["clientSecret":"Google\Auth\OAuth2":private]=>
    string(24) "(my client secret)"
    ["username":"Google\Auth\OAuth2":private]=>
    NULL
    ["password":"Google\Auth\OAuth2":private]=>
    NULL
    ["scope":"Google\Auth\OAuth2":private]=>
    NULL
    ["state":"Google\Auth\OAuth2":private]=>
    NULL
    ["code":"Google\Auth\OAuth2":private]=>
    NULL
    ["issuer":"Google\Auth\OAuth2":private]=>
    string(72) "(my clientId).apps.googleusercontent.com"
    ["audience":"Google\Auth\OAuth2":private]=>
    NULL
    ["sub":"Google\Auth\OAuth2":private]=>
    NULL
    ["expiry":"Google\Auth\OAuth2":private]=>
    int(3600)
    ["signingKey":"Google\Auth\OAuth2":private]=>
    NULL
    ["signingAlgorithm":"Google\Auth\OAuth2":private]=>
    NULL
    ["refreshToken":"Google\Auth\OAuth2":private]=>
    NULL
    ["accessToken":"Google\Auth\OAuth2":private]=>
    NULL
    ["idToken":"Google\Auth\OAuth2":private]=>
    NULL
    ["expiresIn":"Google\Auth\OAuth2":private]=>
    NULL
    ["expiresAt":"Google\Auth\OAuth2":private]=>
    NULL
    ["issuedAt":"Google\Auth\OAuth2":private]=>
    NULL
    ["grantType":"Google\Auth\OAuth2":private]=>
    NULL
    ["extensionParams":"Google\Auth\OAuth2":private]=>
    array(0) {
    }
  }
  ["http":"Google_Client":private]=>
  NULL
  ["cache":"Google_Client":private]=>
  NULL
  ["token":"Google_Client":private]=>
  NULL
  ["config":"Google_Client":private]=>
  array(23) {
    ["application_name"]=>
    string(0) ""
    ["base_path"]=>
    string(26) "https://www.googleapis.com"
    ["client_id"]=>
    string(72) "(my clientId).apps.googleusercontent.com"
    ["client_secret"]=>
    string(24) "(my client secret)"
    ["redirect_uri"]=>
    string(47) "(my redirect URL)"
    ["state"]=>
    NULL
    ["developer_key"]=>
    string(0) ""
    ["use_application_default_credentials"]=>
    bool(false)
    ["signing_key"]=>
    NULL
    ["signing_algorithm"]=>
    NULL
    ["subject"]=>
    NULL
    ["hd"]=>
    string(0) ""
    ["prompt"]=>
    string(0) ""
    ["openid.realm"]=>
    string(0) ""
    ["include_granted_scopes"]=>
    NULL
    ["login_hint"]=>
    string(0) ""
    ["request_visible_actions"]=>
    string(0) ""
    ["access_type"]=>
    string(7) "offline"
    ["approval_prompt"]=>
    string(5) "force"
    ["retry"]=>
    array(0) {
    }
    ["cache_config"]=>
    array(0) {
    }
    ["token_callback"]=>
    NULL
    ["jwt"]=>
    NULL
  }
  ["logger":"Google_Client":private]=>
  NULL
  ["deferExecution":"Google_Client":private]=>
  bool(false)
  ["requestedScopes":protected]=>
  array(2) {
    [0]=>
    string(24) "https://mail.google.com/"
    [1]=>
    string(45) "https://www.googleapis.com/auth/gmail.compose"
  }
}

Thanks again for your help!


来源: stackexchange

问:
Kubernetes private registry doesn't work
I'm using these configs: https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/registry

registry.yml:

```<code>apiVersion: v1
kind: ReplicationController
metadata:
  name: kube-registry-v0
  namespace: default
  labels:
    k8s-app: kube-registry
    version: v0
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  selector:
    k8s-app: kube-registry
    version: v0
  template:
    metadata:
      labels:
        k8s-app: kube-registry
        version: v0
        kubernetes.io/cluster-service: "true"
    spec:
      containers:
      - name: registry
        image: registry:2
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        env:
        - name: REGISTRY_HTTP_ADDR
          value: :5050
        - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
          value: /var/lib/registry
        volumeMounts:
        - name: image-store
          mountPath: /var/lib/registry
        ports:
        - containerPort: 5050
          name: registry
          protocol: TCP
      volumes:
      - name: image-store
        emptyDir: {}
</code>```

registry-service.yml:

```<code>apiVersion: v1
kind: Service
metadata:
  name: kube-registry
  namespace: default
  labels:
    k8s-app: kube-registry
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeRegistry"
spec:
  selector:
    k8s-app: kube-registry
  ports:
  - name: registry
    port: 5050
    protocol: TCP
</code>```

registry-expose.yml:

```<code>apiVersion: v1
kind: Pod
metadata:
  name: kube-registry-proxy
  namespace: default
spec:
  containers:
  - name: kube-registry-proxy
    image: gcr.io/google_containers/kube-registry-proxy:0.3
    resources:
      limits:
        cpu: 100m
        memory: 50Mi
    env:
    - name: REGISTRY_HOST
      value: kube-registry.kube-system.svc.cluster.local
    - name: REGISTRY_PORT
      value: "5050"
    - name: FORWARD_PORT
      value: "5050"
    ports:
    - name: registry
      containerPort: 5050
      hostPort: 5050
</code>```

Status:

```<code>$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
kube-registry-proxy      1/1       Running   0          33m
kube-registry-v0-m57gk   1/1       Running   1          33m

$ kubectl get services
NAME            CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kube-registry   10.98.134.140   <none>        5050/TCP   34m
kubernetes      10.96.0.1       <none>        443/TCP    2h

$ kubectl get componentstatuses
NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health": "true"}
</code>```

Can't see what's happening:

```<code>$ kubectl exec -it kube-registry-v0-m57gk -- bash
rpc error: code = 2 desc = containerd: container not started
</code>```

There is no 5050 port opened on the host, but I'm unsure if it's the desired outcome or not. From inside the kube-registry-proxy some other containers can be pinged, but there are not enough tools installed to see clearly.

How to make the local registry work?

答: Run kubectl describe pod kube-registry-v0-m57gk and check pod status? It seems like container in kube-registry-v0-m57gk does't start correctly.

ContentLicense: CC BY-SA 3.0

Body:
I'm using these configs: https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/registry

registry.yml:

apiVersion: v1
kind: ReplicationController
metadata:
  name: kube-registry-v0
  namespace: default
  labels:
    k8s-app: kube-registry
    version: v0
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  selector:
    k8s-app: kube-registry
    version: v0
  template:
    metadata:
      labels:
        k8s-app: kube-registry
        version: v0
        kubernetes.io/cluster-service: "true"
    spec:
      containers:
      - name: registry
        image: registry:2
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        env:
        - name: REGISTRY_HTTP_ADDR
          value: :5050
        - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
          value: /var/lib/registry
        volumeMounts:
        - name: image-store
          mountPath: /var/lib/registry
        ports:
        - containerPort: 5050
          name: registry
          protocol: TCP
      volumes:
      - name: image-store
        emptyDir: {}

registry-service.yml:

apiVersion: v1
kind: Service
metadata:
  name: kube-registry
  namespace: default
  labels:
    k8s-app: kube-registry
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeRegistry"
spec:
  selector:
    k8s-app: kube-registry
  ports:
  - name: registry
    port: 5050
    protocol: TCP

registry-expose.yml:

apiVersion: v1
kind: Pod
metadata:
  name: kube-registry-proxy
  namespace: default
spec:
  containers:
  - name: kube-registry-proxy
    image: gcr.io/google_containers/kube-registry-proxy:0.3
    resources:
      limits:
        cpu: 100m
        memory: 50Mi
    env:
    - name: REGISTRY_HOST
      value: kube-registry.kube-system.svc.cluster.local
    - name: REGISTRY_PORT
      value: "5050"
    - name: FORWARD_PORT
      value: "5050"
    ports:
    - name: registry
      containerPort: 5050
      hostPort: 5050

Status:

$ kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
kube-registry-proxy      1/1       Running   0          33m
kube-registry-v0-m57gk   1/1       Running   1          33m

$ kubectl get services
NAME            CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kube-registry   10.98.134.140   <none>        5050/TCP   34m
kubernetes      10.96.0.1       <none>        443/TCP    2h

$ kubectl get componentstatuses
NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health": "true"}

Can't see what's happening:

$ kubectl exec -it kube-registry-v0-m57gk -- bash
rpc error: code = 2 desc = containerd: container not started

There is no 5050 port opened on the host, but I'm unsure if it's the desired outcome or not. From inside the kube-registry-proxy some other containers can be pinged, but there are not enough tools installed to see clearly.

How to make the local registry work?


问:
Graphene mutation not mapping Models in SQL Alchemy
I am trying to perform mutation on User models declared using SQL ALCHEMY.
Here is the code for my models.py file

```<code># blog/models.py
from sqlalchemy import *
from sqlalchemy.orm import (scoped_session, sessionmaker, relationship,
                            backref)
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:///database.sqlite3', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base = declarative_base()
# We will need this for querying
Base.query = db_session.query_property()

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key= True)
    name = Column(String)
    email = Column(String)
    posts = relationship("Post", backref="user")

class Post(Base):
    __tablename__ = 'post'
    id = Column(Integer, primary_key= True)
    title = Column(String)
    text = Column(Text)
    user_id = Column(Integer, ForeignKey('user.id'))
</code>```

This is Schema.py file

```<code>import graphene
from graphene import relay
from graphene_sqlalchemy import SQLAlchemyObjectType, SQLAlchemyConnectionField
from models import db_session,User as UserModel, Post as PostModel
from sqlalchemy import *

class User(SQLAlchemyObjectType):
    class Meta:
        model = UserModel
        interfaces = (relay.Node, )

class Post(SQLAlchemyObjectType):
    class Meta:
        model = PostModel
        interfaces = (relay.Node, )

class CreateUser(graphene.Mutation):
    class Input:
        name = graphene.String()

    ok = graphene.Boolean()
    user = graphene.Field(User)

    @classmethod
    def mutate(cls, instance, args, context, info):
        new_user = User(name=args.get('name'))

        db_session.add(new_user)
        db_session.commit()
        ok = True
        return CreateUser(user=new_user, ok=ok)

class Query(graphene.ObjectType):
    node = relay.Node.Field()
    user = relay.Node.Field(User)
    allUsers = SQLAlchemyConnectionField(User)

class MyMutations(graphene.ObjectType):
    create_user = CreateUser.Field()

schema = graphene.Schema(query=Query, mutation = MyMutations, types = [User, Post])
</code>```

When i try performing following mutation, this is the error i get :

```<code>--Query--
    mutation Test{
      createUser(name:"tess"){
        ok
        user{
          name
        }
      }
    }

    --Result--
    {
      "errors": [
        {
          "message": "Class 'schema2.User' is not mapped",
          "locations": [
            {
              "line": 2,
              "column": 3
            }
          ]
        }
      ],
      "data": {
        "createUser": null
      }
    }
</code>```

答:
You are trying to create a user with the wrong class. It seems you meant UserModel when you are calling the line User(name=args.get('name'))

The error is correct in that the SQLAlchemyObjectType User is not mapped, the model User which you imported as UserModel is.

Body:
I am trying to perform mutation on User models declared using SQL ALCHEMY.
Here is the code for my models.py file

# blog/models.py
from sqlalchemy import *
from sqlalchemy.orm import (scoped_session, sessionmaker, relationship,
                            backref)
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:///database.sqlite3', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base = declarative_base()
# We will need this for querying
Base.query = db_session.query_property()

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key= True)
    name = Column(String)
    email = Column(String)
    posts = relationship("Post", backref="user")

class Post(Base):
    __tablename__ = 'post'
    id = Column(Integer, primary_key= True)
    title = Column(String)
    text = Column(Text)
    user_id = Column(Integer, ForeignKey('user.id'))

This is Schema.py file

import graphene
from graphene import relay
from graphene_sqlalchemy import SQLAlchemyObjectType, SQLAlchemyConnectionField
from models import db_session,User as UserModel, Post as PostModel
from sqlalchemy import *

class User(SQLAlchemyObjectType):
    class Meta:
        model = UserModel
        interfaces = (relay.Node, )

class Post(SQLAlchemyObjectType):
    class Meta:
        model = PostModel
        interfaces = (relay.Node, )

class CreateUser(graphene.Mutation):
    class Input:
        name = graphene.String()

    ok = graphene.Boolean()
    user = graphene.Field(User)

    @classmethod
    def mutate(cls, instance, args, context, info):
        new_user = User(name=args.get('name'))

        db_session.add(new_user)
        db_session.commit()
        ok = True
        return CreateUser(user=new_user, ok=ok)

class Query(graphene.ObjectType):
    node = relay.Node.Field()
    user = relay.Node.Field(User)
    allUsers = SQLAlchemyConnectionField(User)

class MyMutations(graphene.ObjectType):
    create_user = CreateUser.Field()

schema = graphene.Schema(query=Query, mutation = MyMutations, types = [User, Post])

When i try performing following mutation, this is the error i get :

--Query--
    mutation Test{
      createUser(name:"tess"){
        ok
        user{
          name
        }
      }
    }

    --Result--
    {
      "errors": [
        {
          "message": "Class 'schema2.User' is not mapped",
          "locations": [
            {
              "line": 2,
              "column": 3
            }
          ]
        }
      ],
      "data": {
        "createUser": null
      }
    }


问:
How to use readarray / mapfile on only a portion of a file?
I'm working with molecular coordinate files, where the first line is the number of atoms followed by a blank line, and each line following being the x, y, and z coordinates for a given atom.

```<code>7

O    0    -0.1   -1.5
H    0     0.8   -1.9
H    0     0.1   -0.5
N    0     0      1.5
H    0    -1      1.7
H   -0.8   0.4    1.9
H    0.8   0.4    1.9
</code>```

I would like to create an array where each element is a line of the file, so it would look something like this:

```<code>r1=(O    0    -0.1   -1.5)
r2=(H    0     0.8   -1.9)
</code>```

I would use the readarray or mapfile command, but I only want to make elements out of the 3rd through 10th rows. Is there a way to give those commands ranges?

答:
This seems to work for me, though I'm sure it's not the most efficient:

```<code>#!/bin/bash

i=0
while read line; do
    i=$((i + 1))
    declare -a "r$i"="($line)"
done < <(sed -n '3,10p' coords.txt)

# do stuff with $r1, $r2, etc
echo "${r1[@]}"
echo "${r2[@]}"
echo "${r3[@]}"
echo "${r4[@]}"
echo "${r5[@]}"
echo "${r6[@]}"
echo "${r7[@]}"
</code>```

We use an address range to have sed only print the desired line numbers. Feed that into a loop, where we use declare to create an array with a variable name.

Body:
I'm working with molecular coordinate files, where the first line is the number of atoms followed by a blank line, and each line following being the x, y, and z coordinates for a given atom.

7

O    0    -0.1   -1.5
H    0     0.8   -1.9
H    0     0.1   -0.5
N    0     0      1.5
H    0    -1      1.7
H   -0.8   0.4    1.9
H    0.8   0.4    1.9

I would like to create an array where each element is a line of the file, so it would look something like this:

r1=(O    0    -0.1   -1.5)
r2=(H    0     0.8   -1.9)

I would use the readarray or mapfile command, but I only want to make elements out of the 3rd through 10th rows. Is there a way to give those commands ranges?

Body:
This seems to work for me, though I'm sure it's not the most efficient:

#!/bin/bash

i=0
while read line; do
    i=$((i + 1))
    declare -a "r$i"="($line)"
done < <(sed -n '3,10p' coords.txt)

# do stuff with $r1, $r2, etc
echo "${r1[@]}"
echo "${r2[@]}"
echo "${r3[@]}"
echo "${r4[@]}"
echo "${r5[@]}"
echo "${r6[@]}"
echo "${r7[@]}"

We use an address range to have sed only print the desired line numbers. Feed that into a loop, where we use declare to create an array with a variable name.


问:
Which loop syntax is the fastest for Array Datatype in Libgdx?
```<code>public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

public void two() {
    int sum = 0;
    for (Foo a : mArray) {
        sum += a.mSplat;
    }
}
</code>```

Quoting https://developer.android.com/training/articles/perf-tips.html#Loops it's recommend to use 'for each loop syntax' to achieve better performance. But on the other hand the article says that it does not make any difference for devices with JIT to use zero() or two() whereas zero() is the slowest.

Ive also found articles where it's not recommend to use two() but one() because a for each loop may create garbage.

I want to know what is the best to iterate through all elements of an Array Datatype from LibGDX.

Here are some articles:
https://github.com/libgdx/libgdx/wiki/Collections
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Array.html

I'm still confused

答:
two() is better option in my opinion.

Array of Libgdx is optimized to avoid garbage collection as much as possible. They do this in many ways.

One way is the one you already pointed out, by trying to avoid memory  copies when possible.

re-using of iterators.

Use IntArray, that Avoids the boxing that occurs with ArrayList.

Body:
public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

public void two() {
    int sum = 0;
    for (Foo a : mArray) {
        sum += a.mSplat;
    }
}

Quoting https://developer.android.com/training/articles/perf-tips.html#Loops it's recommend to use 'for each loop syntax' to achieve better performance. But on the other hand the article says that it does not make any difference for devices with JIT to use zero() or two() whereas zero() is the slowest.

Ive also found articles where it's not recommend to use two() but one() because a for each loop may create garbage.

I want to know what is the best to iterate through all elements of an Array Datatype from LibGDX.

Here are some articles:
https://github.com/libgdx/libgdx/wiki/Collections
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Array.html

I'm still confused


问:
how to distribute a java-application with libraries such as itext?
I have written an application in java. It uses iText, jXL and JAI.

How do I build a jar which contains all these libraries? Or do I have to force the user to install these too?

答:
Either unpack the jars into your jar, or just add them to the jar classpath via the Class-Path attribute in your meta-inf, and distribute the libraries along with your main jar. Sample META_INF/Manifest.mf:</p>

```<code>Manifest-Version: 1.0
Class-Path: itext.jar jxl.jar jai.jar
Main-Class: com.xxx.yyy.Main
</code>```

ContentLicense: CC BY-SA 2.5

Body:
Either unpack the jars into your jar, or just add them to the jar classpath via the Class-Path attribute in your meta-inf, and distribute the libraries along with your main jar. Sample META_INF/Manifest.mf:

Manifest-Version: 1.0
Class-Path: itext.jar jxl.jar jai.jar
Main-Class: com.xxx.yyy.Main


问:
remove function returning false for record that should be in hash table
I am making a hash table that uses linear probing as the collision resolution method. I have tested my other functions and they are working as intended, I just can't seem to figure out what's going wrong in the remove. I am attempting to use the lazy deletion strategy of just having a bool flag marked as deleted or not in the records. I assume i am missing a logical step somewhere since the key that should be removed is apparently not found when passed to the function. </p>

答:
I see several problems with remove.

The main one is that your idx calculation is wrong in your loop.  It should be

```<code>int idx = (hash + i) % LargerMax;
</code>```

like you have in update.

You're not handling deleted records right.  Think about what your list looks like if you insert two records (A, then B) that have the smae hash value, then delete record A.  How do you find B?  (Ponder this before reading on.)

As you walk thru records_, when you find a deleted node, you need to skip it and move on to the next one.  Only stop searching when you find a NULL record.

You also need to return false at the end of the function, if you've searched thru all the nodes and didn't find it.

Body:
I see several problems with remove.

The main one is that your idx calculation is wrong in your loop.  It should be

int idx = (hash + i) % LargerMax;

like you have in update.

You're not handling deleted records right.  Think about what your list looks like if you insert two records (A, then B) that have the smae hash value, then delete record A.  How do you find B?  (Ponder this before reading on.)

As you walk thru records_, when you find a deleted node, you need to skip it and move on to the next one.  Only stop searching when you find a NULL record.

You also need to return false at the end of the function, if you've searched thru all the nodes and didn't find it.


问:
can't run sublime text
after I install sublime-text on ubuntu, I have tried 16.04 32 bit and 64 bit, I get many errors when I try to run it with the command prompt subl.

This is how I am installing:

```<code>sudo add-apt-repository ppa:webupd8team/sublime-text-3
sudo apt-get update
sudo apt-get install sublime-text-installer
</code>```

after this I have checked that subl exists in my /usr/bin/ directory

Below is the error I receive when I run subl in the command line, please help, thank you:

Unable to load libgdk-x11-2.0.so Unable to load gdk_cairo_create from
  libgdk-x11-2.0.so Unable to load gdk_cursor_new_for_display from
  libgdk-x11-2.0.so Unable to load gdk_cursor_unref from
  libgdk-x11-2.0.so Unable to load gdk_display_get_default from
  libgdk-x11-2.0.so Unable to load gdk_display_get_pointer from
  libgdk-x11-2.0.so Unable to load gdk_error_trap_pop from
  libgdk-x11-2.0.so Unable to load gdk_error_trap_push from
  libgdk-x11-2.0.so Unable to load gdk_input_add from libgdk-x11-2.0.so
  Unable to load gdk_input_remove from libgdk-x11-2.0.so Unable to load
  gdk_keymap_translate_keyboard_state from libgdk-x11-2.0.so Unable to
  load gdk_keyval_to_unicode from libgdk-x11-2.0.so Unable to load
  gdk_pixbuf_new_from_file from libgdk-x11-2.0.so Unable to load
  gdk_region_get_rectangles from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_default from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_display from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_height from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_rgb_colormap from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_rgba_colormap from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_root_window from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_width from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_n_monitors from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_monitor_at_point from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_monitor_geometry from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_resolution from libgdk-x11-2.0.so Unable to load
  gdk_unicode_to_keyval from libgdk-x11-2.0.so Unable to load
  gdk_window_get_frame_extents from libgdk-x11-2.0.so Unable to load
  gdk_window_get_origin from libgdk-x11-2.0.so Unable to load
  gdk_window_get_state from libgdk-x11-2.0.so Unable to load
  gdk_window_invalidate_rect from libgdk-x11-2.0.so Unable to load
  gdk_window_set_cursor from libgdk-x11-2.0.so Unable to load
  gdk_window_move_resize from libgdk-x11-2.0.so Unable to load
  gdk_x11_display_get_xdisplay from libgdk-x11-2.0.so Unable to load
  gdk_x11_drawable_get_xid from libgdk-x11-2.0.so Unable to load
  gdk_x11_get_server_time from libgdk-x11-2.0.so Unable to load
  gdk_x11_get_xatom_by_name_for_display from libgdk-x11-2.0.so Unable to
  load gdk_x11_window_set_user_time from libgdk-x11-2.0.so Unable to
  load libgtk-x11-2.0.so Unable to load gtk_accel_group_new from
  libgtk-x11-2.0.so Unable to load gtk_accelerator_get_default_mod_mask
  from libgtk-x11-2.0.so Unable to load gtk_box_get_type from
  libgtk-x11-2.0.so Unable to load gtk_box_pack_start from
  libgtk-x11-2.0.so Unable to load gtk_check_menu_item_get_type from
  libgtk-x11-2.0.so Unable to load gtk_check_menu_item_new_with_label
  from libgtk-x11-2.0.so Unable to load gtk_check_menu_item_set_active
  from libgtk-x11-2.0.so Unable to load gtk_clipboard_clear from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_get from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_set_text from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_set_with_data from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_store from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_wait_for_text from
  libgtk-x11-2.0.so Unable to load gtk_container_add from
  libgtk-x11-2.0.so Unable to load gtk_container_get_children from
  libgtk-x11-2.0.so Unable to load gtk_container_get_type from
  libgtk-x11-2.0.so Unable to load gtk_container_remove from
  libgtk-x11-2.0.so Unable to load gtk_dialog_add_button from
  libgtk-x11-2.0.so Unable to load gtk_dialog_get_type from
  libgtk-x11-2.0.so Unable to load gtk_dialog_run from libgtk-x11-2.0.so
  Unable to load gtk_dialog_set_default_response from libgtk-x11-2.0.so
  Unable to load gtk_drag_dest_set from libgtk-x11-2.0.so Unable to load
  gtk_drag_finish from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_add_filter from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_dialog_new from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_get_filename from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_get_files from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_get_type from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_set_current_folder from libgtk-x11-2.0.so Unable to
  load gtk_file_chooser_set_current_name from libgtk-x11-2.0.so Unable
  to load gtk_file_chooser_set_do_overwrite_confirmation from
  libgtk-x11-2.0.so Unable to load gtk_file_chooser_set_local_only from
  libgtk-x11-2.0.so Unable to load gtk_file_chooser_set_select_multiple
  from libgtk-x11-2.0.so Unable to load gtk_file_filter_add_pattern from
  libgtk-x11-2.0.so Unable to load gtk_file_filter_new from
  libgtk-x11-2.0.so Unable to load gtk_file_filter_set_name from
  libgtk-x11-2.0.so Unable to load gtk_get_current_event_time from
  libgtk-x11-2.0.so Unable to load gtk_im_context_filter_keypress from
  libgtk-x11-2.0.so Unable to load gtk_im_context_set_client_window from
  libgtk-x11-2.0.so Unable to load gtk_im_multicontext_new from
  libgtk-x11-2.0.so Unable to load gtk_init from libgtk-x11-2.0.so
  Unable to load gtk_init_check from libgtk-x11-2.0.so Unable to load
  gtk_main from libgtk-x11-2.0.so Unable to load gtk_main_quit from
  libgtk-x11-2.0.so Unable to load gtk_menu_attach_to_widget from
  libgtk-x11-2.0.so Unable to load gtk_menu_bar_new from
  libgtk-x11-2.0.so Unable to load gtk_menu_get_type from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_get_label from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_get_submenu from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_get_type from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_new_with_label from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_set_label from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_set_submenu from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_set_use_underline from
  libgtk-x11-2.0.so Unable to load gtk_menu_new from libgtk-x11-2.0.so
  Unable to load gtk_menu_popup from libgtk-x11-2.0.so Unable to load
  gtk_menu_shell_append from libgtk-x11-2.0.so Unable to load
  gtk_menu_shell_get_type from libgtk-x11-2.0.so Unable to load
  gtk_message_dialog_new from libgtk-x11-2.0.so Unable to load
  gtk_message_dialog_new_with_markup from libgtk-x11-2.0.so Unable to
  load gtk_selection_data_get_uris from libgtk-x11-2.0.so Unable to load
  gtk_selection_data_set_text from libgtk-x11-2.0.so Unable to load
  gtk_separator_menu_item_new from libgtk-x11-2.0.so Unable to load
  gtk_settings_get_default from libgtk-x11-2.0.so Unable to load
  gtk_show_uri from libgtk-x11-2.0.so Unable to load gtk_vbox_new from
  libgtk-x11-2.0.so Unable to load gtk_widget_add_accelerator from
  libgtk-x11-2.0.so Unable to load gtk_widget_add_events from
  libgtk-x11-2.0.so Unable to load gtk_widget_destroy from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_display from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_parent from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_screen from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_type from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_window from
  libgtk-x11-2.0.so Unable to load gtk_widget_grab_focus from
  libgtk-x11-2.0.so Unable to load gtk_widget_hide from
  libgtk-x11-2.0.so Unable to load gtk_widget_remove_accelerator from
  libgtk-x11-2.0.so Unable to load gtk_widget_set_app_paintable from
  libgtk-x11-2.0.so Unable to load gtk_widget_set_colormap from
  libgtk-x11-2.0.so Unable to load gtk_widget_set_double_buffered from
  libgtk-x11-2.0.so Unable to load gtk_widget_set_sensitive from
  libgtk-x11-2.0.so Unable to load gtk_widget_show from
  libgtk-x11-2.0.so Unable to load gtk_widget_show_all from
  libgtk-x11-2.0.so Unable to load gtk_widget_size_request from
  libgtk-x11-2.0.so Unable to load gtk_window_add_accel_group from
  libgtk-x11-2.0.so Unable to load gtk_window_fullscreen from
  libgtk-x11-2.0.so Unable to load gtk_window_get_type from
  libgtk-x11-2.0.so Unable to load gtk_window_iconify from
  libgtk-x11-2.0.so Unable to load gtk_window_maximize from
  libgtk-x11-2.0.so Unable to load gtk_window_move from
  libgtk-x11-2.0.so Unable to load gtk_window_new from libgtk-x11-2.0.so
  Unable to load gtk_window_present_with_time from libgtk-x11-2.0.so
  Unable to load gtk_window_remove_accel_group from libgtk-x11-2.0.so
  Unable to load gtk_window_resize from libgtk-x11-2.0.so Unable to load
  gtk_window_set_default_icon_list from libgtk-x11-2.0.so Unable to load
  gtk_window_set_default_size from libgtk-x11-2.0.so Unable to load
  gtk_window_set_keep_above from libgtk-x11-2.0.so Unable to load
  gtk_window_set_modal from libgtk-x11-2.0.so Unable to load
  gtk_window_set_position from libgtk-x11-2.0.so Unable to load
  gtk_window_set_title from libgtk-x11-2.0.so Unable to load
  gtk_window_set_transient_for from libgtk-x11-2.0.so Unable to load
  gtk_window_set_type_hint from libgtk-x11-2.0.so Unable to load
  gtk_window_stick from libgtk-x11-2.0.so Unable to load
  gtk_window_unfullscreen from libgtk-x11-2.0.so Unable to load
  gtk_widget_modify_bg from libgtk-x11-2.0.so Unable to load
  gtk_window_set_decorated from libgtk-x11-2.0.so Unable to load
  gtk_window_set_skip_taskbar_hint from libgtk-x11-2.0.so Unable to load
  gtk_window_set_skip_pager_hint from libgtk-x11-2.0.so

答:
Looks like libgtk is missing in your ubuntu.

You can try installing the same by:

```<code>sudo apt-get install libgtk2.0
</code>```

Title: can't run sublime text

Body:
after I install sublime-text on ubuntu, I have tried 16.04 32 bit and 64 bit, I get many errors when I try to run it with the command prompt subl.

This is how I am installing:

sudo add-apt-repository ppa:webupd8team/sublime-text-3
sudo apt-get update
sudo apt-get install sublime-text-installer

after this I have checked that subl exists in my /usr/bin/ directory

Below is the error I receive when I run subl in the command line, please help, thank you:

Unable to load libgdk-x11-2.0.so Unable to load gdk_cairo_create from
  libgdk-x11-2.0.so Unable to load gdk_cursor_new_for_display from
  libgdk-x11-2.0.so Unable to load gdk_cursor_unref from
  libgdk-x11-2.0.so Unable to load gdk_display_get_default from
  libgdk-x11-2.0.so Unable to load gdk_display_get_pointer from
  libgdk-x11-2.0.so Unable to load gdk_error_trap_pop from
  libgdk-x11-2.0.so Unable to load gdk_error_trap_push from
  libgdk-x11-2.0.so Unable to load gdk_input_add from libgdk-x11-2.0.so
  Unable to load gdk_input_remove from libgdk-x11-2.0.so Unable to load
  gdk_keymap_translate_keyboard_state from libgdk-x11-2.0.so Unable to
  load gdk_keyval_to_unicode from libgdk-x11-2.0.so Unable to load
  gdk_pixbuf_new_from_file from libgdk-x11-2.0.so Unable to load
  gdk_region_get_rectangles from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_default from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_display from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_height from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_rgb_colormap from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_rgba_colormap from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_root_window from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_width from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_n_monitors from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_monitor_at_point from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_monitor_geometry from libgdk-x11-2.0.so Unable to load
  gdk_screen_get_resolution from libgdk-x11-2.0.so Unable to load
  gdk_unicode_to_keyval from libgdk-x11-2.0.so Unable to load
  gdk_window_get_frame_extents from libgdk-x11-2.0.so Unable to load
  gdk_window_get_origin from libgdk-x11-2.0.so Unable to load
  gdk_window_get_state from libgdk-x11-2.0.so Unable to load
  gdk_window_invalidate_rect from libgdk-x11-2.0.so Unable to load
  gdk_window_set_cursor from libgdk-x11-2.0.so Unable to load
  gdk_window_move_resize from libgdk-x11-2.0.so Unable to load
  gdk_x11_display_get_xdisplay from libgdk-x11-2.0.so Unable to load
  gdk_x11_drawable_get_xid from libgdk-x11-2.0.so Unable to load
  gdk_x11_get_server_time from libgdk-x11-2.0.so Unable to load
  gdk_x11_get_xatom_by_name_for_display from libgdk-x11-2.0.so Unable to
  load gdk_x11_window_set_user_time from libgdk-x11-2.0.so Unable to
  load libgtk-x11-2.0.so Unable to load gtk_accel_group_new from
  libgtk-x11-2.0.so Unable to load gtk_accelerator_get_default_mod_mask
  from libgtk-x11-2.0.so Unable to load gtk_box_get_type from
  libgtk-x11-2.0.so Unable to load gtk_box_pack_start from
  libgtk-x11-2.0.so Unable to load gtk_check_menu_item_get_type from
  libgtk-x11-2.0.so Unable to load gtk_check_menu_item_new_with_label
  from libgtk-x11-2.0.so Unable to load gtk_check_menu_item_set_active
  from libgtk-x11-2.0.so Unable to load gtk_clipboard_clear from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_get from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_set_text from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_set_with_data from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_store from
  libgtk-x11-2.0.so Unable to load gtk_clipboard_wait_for_text from
  libgtk-x11-2.0.so Unable to load gtk_container_add from
  libgtk-x11-2.0.so Unable to load gtk_container_get_children from
  libgtk-x11-2.0.so Unable to load gtk_container_get_type from
  libgtk-x11-2.0.so Unable to load gtk_container_remove from
  libgtk-x11-2.0.so Unable to load gtk_dialog_add_button from
  libgtk-x11-2.0.so Unable to load gtk_dialog_get_type from
  libgtk-x11-2.0.so Unable to load gtk_dialog_run from libgtk-x11-2.0.so
  Unable to load gtk_dialog_set_default_response from libgtk-x11-2.0.so
  Unable to load gtk_drag_dest_set from libgtk-x11-2.0.so Unable to load
  gtk_drag_finish from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_add_filter from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_dialog_new from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_get_filename from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_get_files from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_get_type from libgtk-x11-2.0.so Unable to load
  gtk_file_chooser_set_current_folder from libgtk-x11-2.0.so Unable to
  load gtk_file_chooser_set_current_name from libgtk-x11-2.0.so Unable
  to load gtk_file_chooser_set_do_overwrite_confirmation from
  libgtk-x11-2.0.so Unable to load gtk_file_chooser_set_local_only from
  libgtk-x11-2.0.so Unable to load gtk_file_chooser_set_select_multiple
  from libgtk-x11-2.0.so Unable to load gtk_file_filter_add_pattern from
  libgtk-x11-2.0.so Unable to load gtk_file_filter_new from
  libgtk-x11-2.0.so Unable to load gtk_file_filter_set_name from
  libgtk-x11-2.0.so Unable to load gtk_get_current_event_time from
  libgtk-x11-2.0.so Unable to load gtk_im_context_filter_keypress from
  libgtk-x11-2.0.so Unable to load gtk_im_context_set_client_window from
  libgtk-x11-2.0.so Unable to load gtk_im_multicontext_new from
  libgtk-x11-2.0.so Unable to load gtk_init from libgtk-x11-2.0.so
  Unable to load gtk_init_check from libgtk-x11-2.0.so Unable to load
  gtk_main from libgtk-x11-2.0.so Unable to load gtk_main_quit from
  libgtk-x11-2.0.so Unable to load gtk_menu_attach_to_widget from
  libgtk-x11-2.0.so Unable to load gtk_menu_bar_new from
  libgtk-x11-2.0.so Unable to load gtk_menu_get_type from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_get_label from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_get_submenu from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_get_type from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_new_with_label from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_set_label from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_set_submenu from
  libgtk-x11-2.0.so Unable to load gtk_menu_item_set_use_underline from
  libgtk-x11-2.0.so Unable to load gtk_menu_new from libgtk-x11-2.0.so
  Unable to load gtk_menu_popup from libgtk-x11-2.0.so Unable to load
  gtk_menu_shell_append from libgtk-x11-2.0.so Unable to load
  gtk_menu_shell_get_type from libgtk-x11-2.0.so Unable to load
  gtk_message_dialog_new from libgtk-x11-2.0.so Unable to load
  gtk_message_dialog_new_with_markup from libgtk-x11-2.0.so Unable to
  load gtk_selection_data_get_uris from libgtk-x11-2.0.so Unable to load
  gtk_selection_data_set_text from libgtk-x11-2.0.so Unable to load
  gtk_separator_menu_item_new from libgtk-x11-2.0.so Unable to load
  gtk_settings_get_default from libgtk-x11-2.0.so Unable to load
  gtk_show_uri from libgtk-x11-2.0.so Unable to load gtk_vbox_new from
  libgtk-x11-2.0.so Unable to load gtk_widget_add_accelerator from
  libgtk-x11-2.0.so Unable to load gtk_widget_add_events from
  libgtk-x11-2.0.so Unable to load gtk_widget_destroy from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_display from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_parent from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_screen from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_type from
  libgtk-x11-2.0.so Unable to load gtk_widget_get_window from
  libgtk-x11-2.0.so Unable to load gtk_widget_grab_focus from
  libgtk-x11-2.0.so Unable to load gtk_widget_hide from
  libgtk-x11-2.0.so Unable to load gtk_widget_remove_accelerator from
  libgtk-x11-2.0.so Unable to load gtk_widget_set_app_paintable from
  libgtk-x11-2.0.so Unable to load gtk_widget_set_colormap from
  libgtk-x11-2.0.so Unable to load gtk_widget_set_double_buffered from
  libgtk-x11-2.0.so Unable to load gtk_widget_set_sensitive from
  libgtk-x11-2.0.so Unable to load gtk_widget_show from
  libgtk-x11-2.0.so Unable to load gtk_widget_show_all from
  libgtk-x11-2.0.so Unable to load gtk_widget_size_request from
  libgtk-x11-2.0.so Unable to load gtk_window_add_accel_group from
  libgtk-x11-2.0.so Unable to load gtk_window_fullscreen from
  libgtk-x11-2.0.so Unable to load gtk_window_get_type from
  libgtk-x11-2.0.so Unable to load gtk_window_iconify from
  libgtk-x11-2.0.so Unable to load gtk_window_maximize from
  libgtk-x11-2.0.so Unable to load gtk_window_move from
  libgtk-x11-2.0.so Unable to load gtk_window_new from libgtk-x11-2.0.so
  Unable to load gtk_window_present_with_time from libgtk-x11-2.0.so
  Unable to load gtk_window_remove_accel_group from libgtk-x11-2.0.so
  Unable to load gtk_window_resize from libgtk-x11-2.0.so Unable to load
  gtk_window_set_default_icon_list from libgtk-x11-2.0.so Unable to load
  gtk_window_set_default_size from libgtk-x11-2.0.so Unable to load
  gtk_window_set_keep_above from libgtk-x11-2.0.so Unable to load
  gtk_window_set_modal from libgtk-x11-2.0.so Unable to load
  gtk_window_set_position from libgtk-x11-2.0.so Unable to load
  gtk_window_set_title from libgtk-x11-2.0.so Unable to load
  gtk_window_set_transient_for from libgtk-x11-2.0.so Unable to load
  gtk_window_set_type_hint from libgtk-x11-2.0.so Unable to load
  gtk_window_stick from libgtk-x11-2.0.so Unable to load
  gtk_window_unfullscreen from libgtk-x11-2.0.so Unable to load
  gtk_widget_modify_bg from libgtk-x11-2.0.so Unable to load
  gtk_window_set_decorated from libgtk-x11-2.0.so Unable to load
  gtk_window_set_skip_taskbar_hint from libgtk-x11-2.0.so Unable to load
  gtk_window_set_skip_pager_hint from libgtk-x11-2.0.so

Body:
Looks like libgtk is missing in your ubuntu.

You can try installing the same by:

sudo apt-get install libgtk2.0


问:
how to save my recharts to a html file with R
below is my code to get a rechart:

```<code>recharts.emap <- eMap(df,namevar=1,datavar=2,title=title)
</code>```

when I run the code below:recharts.emap
It runs well and create the Interactive picture:

now, I want to know how to save the the Interactive picture into a HTML file! I got a method beforehtmlwidgets::saveWidget(recharts.emap,file=ofile),but it faild.Look forward to you answer.Thank you.

答:
You could look at RMarkdown. I tried a sample dataset mapTestData_chs.

Here is what I did.

```<code>```{r}
library(recharts)
mapData <- head(mapTestData_chs, 5)
eMap(mapData, namevar=~stdName, datavar = ~val1 + val2)
```
</code>```

This is called a chunk. You can find the result below:

Body:
below is my code to get a rechart:

recharts.emap <- eMap(df,namevar=1,datavar=2,title=title)

when I run the code below:recharts.emap
It runs well and create the Interactive picture:

now, I want to know how to save the the Interactive picture into a HTML file! I got a method beforehtmlwidgets::saveWidget(recharts.emap,file=ofile),but it faild.Look forward to you answer.Thank you.

Body:
You could look at RMarkdown. I tried a sample dataset mapTestData_chs.

Here is what I did.

```{r}
library(recharts)
mapData <- head(mapTestData_chs, 5)
eMap(mapData, namevar=~stdName, datavar = ~val1 + val2)
```

This is called a chunk. You can find the result below:


问:
PyQt5: QSlider valueChanged event with delay
I'm using QSlider in my GUI application in order to perform a heavy task after value changed in the QSlider. I'm doing that as follows.

```<code>self.slider.valueChanged.connect(self.value_changed)  # Inside __init__() function

def value_changed(self):  # Inside the class
    # Do the heavy task
</code>```

But I can't change the value of the slider smoothly because the heavy task is running every time I change the value.

What I need is to run the heavy task after the value changed but only if the value of the slider is not changing for a while.

I can't figure out how to  do this in python. Any help..?

答:
You can use startTimer/killTimer to delay your task:

```<code>class Foo(QWidget):
    def __init__(self):
        super().__init__()
        self.timer_id = -1
        self.slider = QSlider(self)
        self.slider.setMinimum(0)
        self.slider.setMaximum(100)
        self.slider.valueChanged.connect(self.value_changed)

    def timerEvent(self, event):
        self.killTimer(self.timer_id)
        self.timer_id = -1
        heavy_task()

    def value_changed(self):
        if self.timer_id != -1:
            self.killTimer(self.timer_id)

        self.timer_id = self.startTimer(3000)
</code>```

so, as can you see we restart timer every time when
user something change, so if 3000 millseconds not expires
since last change heavy_task not run,

but any way it will be running in main thread, so for some
time interface freeze for user, so you should use
QThread in timerEvent to not have interface that not freeze during
heavy_task execution.

Body:
I'm using QSlider in my GUI application in order to perform a heavy task after value changed in the QSlider. I'm doing that as follows.

self.slider.valueChanged.connect(self.value_changed)  # Inside __init__() function

def value_changed(self):  # Inside the class
    # Do the heavy task

But I can't change the value of the slider smoothly because the heavy task is running every time I change the value.

What I need is to run the heavy task after the value changed but only if the value of the slider is not changing for a while.

I can't figure out how to  do this in python. Any help..?

Body:
You can use startTimer/killTimer to delay your task:

class Foo(QWidget):
    def __init__(self):
        super().__init__()
        self.timer_id = -1
        self.slider = QSlider(self)
        self.slider.setMinimum(0)
        self.slider.setMaximum(100)
        self.slider.valueChanged.connect(self.value_changed)

    def timerEvent(self, event):
        self.killTimer(self.timer_id)
        self.timer_id = -1
        heavy_task()

    def value_changed(self):
        if self.timer_id != -1:
            self.killTimer(self.timer_id)

        self.timer_id = self.startTimer(3000)

so, as can you see we restart timer every time when
user something change, so if 3000 millseconds not expires
since last change heavy_task not run,

but any way it will be running in main thread, so for some
time interface freeze for user, so you should use
QThread in timerEvent to not have interface that not freeze during
heavy_task execution.


问:
node js request module - how to trace redirects?
Lets suppose I want to get some page and when server get my request, it redirect me few times. How to detect those redirects when using request? I would like to see full redirection path if this is possible.

Also I notice that when I visit some pages - I'm redirected from somepage.com/blah to somepage.com and the status is 200? How?

答:
Install Morgan  on your express server and use the following code :

```<code>`app.use(morgan('dev'));`
</code>```

This will log all the get and post requests to your console.

Body:
Install Morgan  on your express server and use the following code :

`app.use(morgan('dev'));`

This will log all the get and post requests to your console.


问:
Images auto resize with screen height, no scrollbar - CSS
Two days have been passed with it. But I didn't found any solution yet. Conditions is-

1. No scrollbar (vertical or horizontal),

2. Screen height is unknown, so all content (images and text) should be auto-resize with screen height,

My code is here-

```<code><!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HTML Quickstart</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico">
    <!-- Bootstrap fremwork main css -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

    <style>
        #padding{
            padding: 15px;
        }
        img{
            width: 100%;
        }
    </style>
</head>
<body>
    <div class="myDiv">
        <div class="container">
            <div class="row">
                <div class="col-md-4" id="padding">
                    <img src="https://dummyimage.com/300x300/ccc/fff.jpg" class="img-responsive" alt="">
                </div>
                <div class="col-md-4" id="padding">
                    <img src="https://dummyimage.com/300x300/000/fff.jpg" class="img-responsive" alt="">
                </div>
                <div class="col-md-4" id="padding">
                    <img src="https://dummyimage.com/300x300/ccc/fff.jpg" class="img-responsive" alt="">
                </div>
            </div>

            <div class="row">
                <div class="col-md-4" id="padding">
                    <img src="https://dummyimage.com/300x300/000/fff.jpg" class="img-responsive" alt="">
                </div>
                <div class="col-md-4" id="padding">
                    <img src="https://dummyimage.com/300x300/ccc/fff.jpg" class="img-responsive" alt="">
                </div>
                <div class="col-md-4" id="padding">
                    <img src="https://dummyimage.com/300x300/000/fff.jpg" class="img-responsive" alt="">
                </div>
            </div>

            <div class="row">
                <div class="col-md-4" id="padding">
                    <img src="https://dummyimage.com/300x300/ccc/fff.jpg" class="img-responsive" alt="">
                </div>
                <div class="col-md-4" id="padding">
                    <img src="https://dummyimage.com/300x300/000/fff.jpg" class="img-responsive" alt="">
                </div>
                <div class="col-md-4" id="padding">
                    <img src="https://dummyimage.com/300x300/ccc/fff.jpg" class="img-responsive" alt="">
                </div>
            </div>

            <div class="row">
                <div class="col-md-12"><h2>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis dignissimosus.</h2></div>
            </div>

        </div>  <!-- end container -->
    </div> <!-- end myDiv -->

</body>
</html>
</code>```

I've tried with this link and it.

Since content (not many contents) is large than screen height, so is it possible to adapt screen height?

Please write a comment if you've any solution, suggestion or anything.

Thanks.

答:
You can use Flex box for layout. I've removed Bootstrap grid code to avoid confliction. Also, id padding is used multiple times, which is fixed in below  code too.

<!DOCTYPE html>

  <meta charset="UTF-8">
  <title>HTML Quickstart</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico">

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis dignissimosus.

```

Body:
Two days have been passed with it. But I didn't found any solution yet. Conditions is-

1. No scrollbar (vertical or horizontal),

2. Screen height is unknown, so all content (images and text) should be auto-resize with screen height,

My code is here-

<!DOCTYPE html>

    <meta charset="UTF-8">
    <title>HTML Quickstart</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico">

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis dignissimosus.

I've tried with this link and it.

Since content (not many contents) is large than screen height, so is it possible to adapt screen height?

Please write a comment if you've any solution, suggestion or anything.

Thanks.

Body:
You can use Flex box for layout. I've removed Bootstrap grid code to avoid confliction. Also, id padding is used multiple times, which is fixed in below  code too.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>HTML Quickstart</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico">
  <!-- Bootstrap fremwork main css -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

  <style>
    html, body, .myDiv, .container {
      height: 100%;
    }
    .container {
      display: flex;
      flex-direction: column;
    }
    .container .image {
      flex: 1;
      display: flex;
      flex-direction: row;
    }
    .container .image img {
      flex: 1;
    }
    .padding{
      padding: 15px;
      flex: 1;
    }
    img{
      width: 100%;
      height: 100% !important;
    }
  </style>
</head>
<body>
<div class="myDiv">
  <div class="container">
    <div class="row image">
      <div class="padding">
        <img src="https://dummyimage.com/300x300/ccc/fff.jpg" alt="">
      </div>
      <div class="padding">
        <img src="https://dummyimage.com/300x300/000/fff.jpg" alt="">
      </div>
      <div class="padding">
        <img src="https://dummyimage.com/300x300/ccc/fff.jpg" alt="">
      </div>
    </div>

    <div class="row image">
      <div class="padding">
        <img src="https://dummyimage.com/300x300/000/fff.jpg" alt="">
      </div>
      <div class="padding">
        <img src="https://dummyimage.com/300x300/ccc/fff.jpg" alt="">
      </div>
      <div class="padding">
        <img src="https://dummyimage.com/300x300/000/fff.jpg" alt="">
      </div>
    </div>

    <div class="row image">
      <div class="padding">
        <img src="https://dummyimage.com/300x300/ccc/fff.jpg" alt="">
      </div>
      <div class="padding">
        <img src="https://dummyimage.com/300x300/000/fff.jpg" alt="">
      </div>
      <div class="padding">
        <img src="https://dummyimage.com/300x300/ccc/fff.jpg" alt="">
      </div>
    </div>

    <div class="row text">
      <div class="col-md-12"><h2>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis dignissimosus.</h2></div>
    </div>

  </div>  <!-- end container -->
</div> <!-- end myDiv -->

</body>
</html>


问:
Inserting JSON into MySQL using Python
I have a JSON object in Python.  I am Using Python DB-API and SimpleJson. I am trying to insert the json into a MySQL table.

At moment am getting errors and I believe it is due to the single quotes '' in the JSON Objects.

How can I insert my JSON Object into MySQL using Python?

Here is the error message I get:

```<code>error: uncaptured python exception, closing channel
<twitstream.twitasync.TwitterStreamPOST connected at
0x7ff68f91d7e8> (<class '_mysql_exceptions.ProgrammingError'>:
(1064, "You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for
the right syntax to use near ''favorited': '0',
'in_reply_to_user_id': '52063869', 'contributors':
'NULL', 'tr' at line 1")
[/usr/lib/python2.5/asyncore.py|read|68]
[/usr/lib/python2.5/asyncore.py|handle_read_event|390]
[/usr/lib/python2.5/asynchat.py|handle_read|137]
[/usr/lib/python2.5/site-packages/twitstream-0.1-py2.5.egg/
twitstream/twitasync.py|found_terminator|55] [twitter.py|callback|26]
[build/bdist.linux-x86_64/egg/MySQLdb/cursors.py|execute|166]
[build/bdist.linux-x86_64/egg/MySQLdb/connections.py|defaulterrorhandler|35])
</code>```

Another error for reference

```<code>error: uncaptured python exception, closing channel
<twitstream.twitasync.TwitterStreamPOST connected at
0x7feb9d52b7e8> (<class '_mysql_exceptions.ProgrammingError'>:
(1064, "You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right
syntax to use near 'RT @tweetmeme The Best BlackBerry Pearl
Cell Phone Covers http://bit.ly/9WtwUO''' at line 1")
[/usr/lib/python2.5/asyncore.py|read|68]
[/usr/lib/python2.5/asyncore.py|handle_read_event|390]
[/usr/lib/python2.5/asynchat.py|handle_read|137]
[/usr/lib/python2.5/site-packages/twitstream-0.1-
py2.5.egg/twitstream/twitasync.py|found_terminator|55]
[twitter.py|callback|28] [build/bdist.linux-
x86_64/egg/MySQLdb/cursors.py|execute|166] [build/bdist.linux-
x86_64/egg/MySQLdb/connections.py|defaulterrorhandler|35])
</code>```

Here is a link to the code that I am using http://pastebin.com/q5QSfYLa

```<code>#!/usr/bin/env python

try:
        import json as simplejson
except ImportError:
        import simplejson

import twitstream
import MySQLdb

USER = ''
PASS = ''

USAGE = """%prog"""

conn = MySQLdb.connect(host = "",
                       user = "",
                       passwd = "",
                       db = "")

# Define a function/callable to be called on every status:
def callback(status):

    twitdb = conn.cursor ()
    twitdb.execute ("INSERT INTO tweets_unprocessed (text, created_at, twitter_id, user_id, user_screen_name, json) VALUES (%s,%s,%s,%s,%s,%s)",(status.get('text'), status.get('created_at'), status.get('id'), status.get('user', {}).get('id'), status.get('user', {}).get('screen_name'), status))

   # print status
     #print "%s:\t%s\n" % (status.get('user', {}).get('screen_name'), status.get('text'))

if __name__ == '__main__':
    # Call a specific API method from the twitstream module:
    # stream = twitstream.spritzer(USER, PASS, callback)

    twitstream.parser.usage = USAGE
    (options, args) = twitstream.parser.parse_args()

    if len(args) < 1:
        args = ['Blackberry']

    stream = twitstream.track(USER, PASS, callback, args, options.debug, engine=options.engine)

    # Loop forever on the streaming call:
    stream.run()
</code>```

答:
You need to get a look at the actual SQL string, try something like this:

```<code>sqlstr = "INSERT INTO tweets_unprocessed (text, created_at, twitter_id, user_id, user_screen_name, json) VALUES (%s,%s,%s,%s,%s,%s)", (status.get('text'), status.get('created_at'), status.get('id'), status.get('user', {}).get('id'), status.get('user', {}).get('screen_name'), status)
print "about to execute(%s)" % sqlstr
twitdb.execute(sqlstr)
</code>```

I imagine you are going to find some stray quotes, brackets or parenthesis in there.

Title: Inserting JSON into MySQL using Python

Body:
I have a JSON object in Python.  I am Using Python DB-API and SimpleJson. I am trying to insert the json into a MySQL table.

At moment am getting errors and I believe it is due to the single quotes '' in the JSON Objects.

How can I insert my JSON Object into MySQL using Python?

Here is the error message I get:

error: uncaptured python exception, closing channel
<twitstream.twitasync.TwitterStreamPOST connected at
0x7ff68f91d7e8> (<class '_mysql_exceptions.ProgrammingError'>:
(1064, "You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for
the right syntax to use near ''favorited': '0',
'in_reply_to_user_id': '52063869', 'contributors':
'NULL', 'tr' at line 1")
[/usr/lib/python2.5/asyncore.py|read|68]
[/usr/lib/python2.5/asyncore.py|handle_read_event|390]
[/usr/lib/python2.5/asynchat.py|handle_read|137]
[/usr/lib/python2.5/site-packages/twitstream-0.1-py2.5.egg/
twitstream/twitasync.py|found_terminator|55] [twitter.py|callback|26]
[build/bdist.linux-x86_64/egg/MySQLdb/cursors.py|execute|166]
[build/bdist.linux-x86_64/egg/MySQLdb/connections.py|defaulterrorhandler|35])

Another error for reference

error: uncaptured python exception, closing channel
<twitstream.twitasync.TwitterStreamPOST connected at
0x7feb9d52b7e8> (<class '_mysql_exceptions.ProgrammingError'>:
(1064, "You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right
syntax to use near 'RT @tweetmeme The Best BlackBerry Pearl
Cell Phone Covers http://bit.ly/9WtwUO''' at line 1")
[/usr/lib/python2.5/asyncore.py|read|68]
[/usr/lib/python2.5/asyncore.py|handle_read_event|390]
[/usr/lib/python2.5/asynchat.py|handle_read|137]
[/usr/lib/python2.5/site-packages/twitstream-0.1-
py2.5.egg/twitstream/twitasync.py|found_terminator|55]
[twitter.py|callback|28] [build/bdist.linux-
x86_64/egg/MySQLdb/cursors.py|execute|166] [build/bdist.linux-
x86_64/egg/MySQLdb/connections.py|defaulterrorhandler|35])

Here is a link to the code that I am using http://pastebin.com/q5QSfYLa

#!/usr/bin/env python

try:
        import json as simplejson
except ImportError:
        import simplejson

import twitstream
import MySQLdb

USER = ''
PASS = ''

USAGE = """%prog"""

conn = MySQLdb.connect(host = "",
                       user = "",
                       passwd = "",
                       db = "")

# Define a function/callable to be called on every status:
def callback(status):

    twitdb = conn.cursor ()
    twitdb.execute ("INSERT INTO tweets_unprocessed (text, created_at, twitter_id, user_id, user_screen_name, json) VALUES (%s,%s,%s,%s,%s,%s)",(status.get('text'), status.get('created_at'), status.get('id'), status.get('user', {}).get('id'), status.get('user', {}).get('screen_name'), status))

   # print status
     #print "%s:\t%s\n" % (status.get('user', {}).get('screen_name'), status.get('text'))

if __name__ == '__main__':
    # Call a specific API method from the twitstream module:
    # stream = twitstream.spritzer(USER, PASS, callback)

    twitstream.parser.usage = USAGE
    (options, args) = twitstream.parser.parse_args()

    if len(args) < 1:
        args = ['Blackberry']

    stream = twitstream.track(USER, PASS, callback, args, options.debug, engine=options.engine)

    # Loop forever on the streaming call:
    stream.run()

Body:
You need to get a look at the actual SQL string, try something like this:

sqlstr = "INSERT INTO tweets_unprocessed (text, created_at, twitter_id, user_id, user_screen_name, json) VALUES (%s,%s,%s,%s,%s,%s)", (status.get('text'), status.get('created_at'), status.get('id'), status.get('user', {}).get('id'), status.get('user', {}).get('screen_name'), status)
print "about to execute(%s)" % sqlstr
twitdb.execute(sqlstr)

I imagine you are going to find some stray quotes, brackets or parenthesis in there.


问:
Makefile: How to export environment variable to shell before target?
I would like to pass makefile variable value to shell variable value:

.makerc:

```<code>IP:=0.0.0.0
</code>```

Makefile:

```<code>-include: .makerc
export IP

all:
    printenv | grep IP
</code>```

I just want IP variable value appear as IP environment variable in shell. I don't want to do this in a target. It has to be off-target.

答:
You have a syntax error in your makefile:

```<code>-include: .makerc
</code>```

is wrong: include is a keyword not a target.  This should be:

```<code>-include .makerc
</code>```

(no colon).

Body:
I would like to pass makefile variable value to shell variable value:

.makerc:

IP:=0.0.0.0

Makefile:

-include: .makerc
export IP

all:
    printenv | grep IP

I just want IP variable value appear as IP environment variable in shell. I don't want to do this in a target. It has to be off-target.

Body:
You have a syntax error in your makefile:

-include: .makerc

is wrong: include is a keyword not a target.  This should be:

-include .makerc

(no colon).


问:
Print page content overwriting on header
page content over writing the header on the second page, please check the below code

```<code> @media screen {
     div.divHeader
            {
                display: none;
            }
    }
    @media print {
      div.divHeader
            {
                position: fixed;
                top: 0;
            }
             div.divContent
            {
                 position: fixed;
                 top: 120px;
            }

    }
</code>```

答:
Got the answer, heading placed in

```<code><table>
     <thead>
    <tr>
    <th colspan="10"><h1>My Header</h1></th></tr>
     </thead>
    <tbody>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    </tbody>
    </table>
</code>```

Body:
page content over writing the header on the second page, please check the below code

 @media screen {
     div.divHeader
            {
                display: none;
            }
    }
    @media print {
      div.divHeader
            {
                position: fixed;
                top: 0;
            }
             div.divContent
            {
                 position: fixed;
                 top: 120px;
            }

    }

Body:
Got the answer, heading placed in <thead>

<table>
     <thead>
    <tr>
    <th colspan="10"><h1>My Header</h1></th></tr>
     </thead>
    <tbody>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
    </tbody>
    </table>


问:
TypeError: 'tuple' object cannot be interpreted as an integer"
I'm trying to make a super basic evolution simulator to generate ten random "creatures" that are each a number value and then give them a random "mutation" but it keeps throwing me this error: "for i in range(creatures):
TypeError: 'tuple' object cannot be interpreted as an integer"</p>

```<code>import random
from random import randint

creatures = (random.randint(1, 10), random.randint(1, 10))

print(creatures)

for i in range(creatures):
    mutation = random.randint(1, 2)
    newEvolution = creatures[i] + mutation

print("New evolution", newEvolution)
</code>```

答:
You need to iterate over the range of the length of the creatures. </p>

```<code>from random import randint
creatures = (random.randint(1, 10), random.randint(1, 10))
print(creatures)
for i in range(len(creatures)): # iterate over the range of the lenght of the creatures
    mutation = random.randint(1, 2)
    newEvolution = creatures[i] + mutation
print("New evolution", newEvolution)
</code>```

Body:
I'm trying to make a super basic evolution simulator to generate ten random "creatures" that are each a number value and then give them a random "mutation" but it keeps throwing me this error: "for i in range(creatures):
TypeError: 'tuple' object cannot be interpreted as an integer"

import random
from random import randint

creatures = (random.randint(1, 10), random.randint(1, 10))

print(creatures)

for i in range(creatures):
    mutation = random.randint(1, 2)
    newEvolution = creatures[i] + mutation

print("New evolution", newEvolution)

Body:
You need to iterate over the range of the length of the creatures.

from random import randint
creatures = (random.randint(1, 10), random.randint(1, 10))
print(creatures)
for i in range(len(creatures)): # iterate over the range of the lenght of the creatures
    mutation = random.randint(1, 2)
    newEvolution = creatures[i] + mutation
print("New evolution", newEvolution)