问:
How to install Python ttk themes
This is my first post on SO, so please feel free to correct me if I'm doing anything wrong!

I am making a simple GUI for my Raspberry Pi (that runs Raspbian stretch) on Windows (because I can use PyCharm on there).
I am would like to install third party themes from this site  and have followed the instructions on the wiki. However, on both Windows and Raspbian, it appears to install properly without any errors, but when I check for ttk by doing this:

```<code>import tkinter.ttk
tkinter.ttk.Style().theme_names()
</code>```

it still displays the default themes for the respective operating systems.

I have also looked at this SO post (How to find or install themes tkinter ttk for Python), but there are no relevant answers on there.

Edit: I now know how to use the themes in a regular tkinter/ttk GUI, but I would like to install these themes so they act like the built in ones, as I am using the appJar module that uses tkinter and ttk.

Any help and guidance would be much appreciated!

答:
appJar's support for ttk is still in development, but you can try overriding the default style:

```<code>from ttkthemes import ThemedStyle
app = gui(useTtk=True)
app.ttkStyle = ThemedStyle(app.topLevel)
app.ttkStyle.set_theme("plastik")
</code>```

This tells appJar to use ttk, but then replaces the style appJar is using, with the style you request.

Title: How to install Python ttk themes

Body:
This is my first post on SO, so please feel free to correct me if I'm doing anything wrong!

I am making a simple GUI for my Raspberry Pi (that runs Raspbian stretch) on Windows (because I can use PyCharm on there).
I am would like to install third party themes from this site  and have followed the instructions on the wiki. However, on both Windows and Raspbian, it appears to install properly without any errors, but when I check for ttk by doing this:

import tkinter.ttk
tkinter.ttk.Style().theme_names()

it still displays the default themes for the respective operating systems.

I have also looked at this SO post (How to find or install themes tkinter ttk for Python), but there are no relevant answers on there.

Edit: I now know how to use the themes in a regular tkinter/ttk GUI, but I would like to install these themes so they act like the built in ones, as I am using the appJar module that uses tkinter and ttk.

Any help and guidance would be much appreciated!

Body:
appJar's support for ttk is still in development, but you can try overriding the default style:

from ttkthemes import ThemedStyle
app = gui(useTtk=True)
app.ttkStyle = ThemedStyle(app.topLevel)
app.ttkStyle.set_theme("plastik")

This tells appJar to use ttk, but then replaces the style appJar is using, with the style you request.


来源: stackexchange

问:
from which version graphql api is supported in github
I am trying to access graphql API in my local github version enterprise 2.7, but its giving error 404 page not found.

Here is url of graphql
https://10.13.28.120/api/v4

So just want to check from which version graphql is supported in github?

答:
From this release note (June 2017), GraphQL API is available from Github enterprise 2.10.0. It isn't available on Github Enterprise 2.7 (and won't likely be implemented as the same release note announce v2.7 deprecation in August 2017)

From Github Enterprise 2.10 documentation, it can be accessed from this endpoint :

```<code>http(s)://[hostname]/api/graphql
</code>```

ContentLicense: CC BY-SA 3.0

Body:
From this release note (June 2017), GraphQL API is available from Github enterprise 2.10.0. It isn't available on Github Enterprise 2.7 (and won't likely be implemented as the same release note announce v2.7 deprecation in August 2017)

From Github Enterprise 2.10 documentation, it can be accessed from this endpoint :

http(s)://[hostname]/api/graphql


问:
WPF DataGrid style-Silverlight DataGrid?
That's not a secret: Silverlight's DataGrid default style is beautiful while WPF's is poor.

Instead of reinventing the wheel let me ask the community if anyone has copied the SL styles to use in WPF.

Please take a look at the screenshots and judge for yourself how the Silverlight and WPF teams invest in their products.

Silverlight default-style DataGrid:

WPF default-style DataGrid (updated after Saied K's answer):

答:
Buried deep within MSDN, I found this.

Toward the bottom of the article, you will see this phrase:

For example, take a look at the following illustration that shows part of the Styling with ControlTemplates Sample

If you click 'Styling with ControlTemplates Sample', it will take you to a download link.  After download, you can compile the project and it includes all kinds of styles, including the elusive datagrid style!  You can take MS's DataGrid.xaml file and modify it for your needs.


问:
Generic, higher order functions
I'm trying to add Flow type information to a small library of mine.

The library defines some functions that are generic over Object, Array, Set, Map and other types.

Here a small piece example to give an idea:

```<code>function set( obj, key, value ) {
  if( isMap(obj) )      { obj.set(key, value); }
  else if( isSet(obj) ) { obj.add(value);      }
  else                  { obj[key] = value;    }
}
function instantiateSameType( obj ) {
  if( isArray(obj) )    { return [];        }
  else if( isMap(obj) ) { return new Map(); }
  else if( isSet(obj) ) { return new Set(); }
  else                  { return {};        }
}
function forEach( obj, fn ) {
  if( obj.forEach ) obj.forEach(    ( value, key )=>fn(value, key, obj) );
  else Object.entries(obj).forEach( ([key, value])=>fn(value, key, obj) );
}
function map( obj, fn ) {
  const result = instantiateSameType( obj );
  forEach(obj, (value, key)=>{
    set( result, key, fn(value, key, this) );
  });
  return result;
}
</code>```

How can I define types for map?

I'd want to avoid giving a specialized version for each of the 4 types I listed in the example, as map is generic over them.
I feel the need to define higher-order interfaces, and implement them for existing types, but can't find much about any of this...

Any hints or ideas?

答:
I wanted to follow up with another answer that matches up with the question that you actually asked. Flow can do just what you want. But it does get a bit painful implementing functions that operate on all four of those collection types because in the case of Map the type for keys is fully generic, but for Array the key type must be number, and due to the way objects are implemented in Javascript the key type for Object is always effectively string. (Set does not have keys, but that does not matter too much because you do not need to use keys to set values in a Set.) The safest way to work around the Array and Object special cases would be to provide an overloaded type signature for every function. But it turns out to be quite difficult to tell Flow that key might be the fully-generic type K or string or number depending on the type of obj. The most practical option is to make each function fully generic in the key type. But you have to remember that these functions will fail if you try to use arrays or plain objects with the wrong key type, and you will not get a type error in those cases.

Let's start with a type for the set of collection types that you are working with:

```<code>type MyIterable<K, V> = Map<K, V> | Set<V> | Array<V> | Pojo<V>
type Pojo<V> = { [key: string]: V } // plain object
</code>```

The collection types must all be listed at this point. If you want to work with an open set of collection types instead then see my other answer. And note that my other answer avoids the type-safety holes in the solution here.

There is a handy trick with Flow: you can put the keyword %checks in the type signature of a function that returns a boolean, and  Flow will be able to use invocations of that function at type-checking time for type refinements. But the body of the function must use constructions that Flow knows how to use for type refinements because Flow does not actually run the function at type-checking time. For example:

```<code>function isMap ( obj: any ): boolean %checks {
  return obj instanceof Map
}

function isSet ( obj: any ): boolean %checks {
  return obj instanceof Set
}

function isArray ( obj: any ): boolean %checks {
  return obj instanceof Array
}
</code>```

I mentioned you would need a couple of type casts. One instance is in set: Flow knows that when assigning to an array index, the index variable should be a number, and it also knows that K might not be number. The same goes for assigning to plain object properties, since the Pojo type alias specifies string keys. So in the code branch for those cases you need to type-cast key to any, which effectively disables type checking for that use of key.

```<code>function set<K, V>( obj: MyIterable<K, V>, key: K, value: V ) {
  if( isMap(obj) )      { obj.set(key, value);    }
  else if( isSet(obj) ) { obj.add(value);         }
  else                  { obj[(key:any)] = value; }
}
</code>```

Your instantiateSameType function just needs a type signature. An important point to keep in mind is that you use instantiateSameType to construct the result of map, and the type of values in the collection can change between the input and output when using map. So it is important to use two different type variables for the value type in the input and output of instantiateSameType as well. You might also allow instantiateSameType to change the key type; but that is not required to make map work correctly.

```<code>function instantiateSameType<K, A, B>( obj: MyIterable<K, A> ): MyIterable<K, B> {
  if( isArray(obj) )    { return [];        }
  else if( isMap(obj) ) { return new Map(); }
  else if( isSet(obj) ) { return new Set(); }
  else                  { return {};        }
}
</code>```

That means that the output of instantiateSameType can hold any of values. It might be the same type as values in the input collection, or it might not.

In your implementation of forEach you check for the presence of obj.forEach as a type refinement. This is confusing to Flow because one of the types that make up MyIterable is a plain Javascript object, which might hold any string key. Flow cannot assume that obj.forEach will be falsy. So you need to use a different check. Re-using the isArray, etc. predicates works well:

```<code>function forEach<K, V, M: MyIterable<K, V>>( obj: M, fn: (value: V, key: K, obj: M) => any ) {
  if( isArray(obj) || isMap(obj) || isSet(obj) ) {
    obj.forEach((value, key) => fn(value, (key:any), obj));
  } else {
    for (const key of Object.keys(obj)) {
      fn(obj[key], (key:any), obj)
    }
  }
}
</code>```

There are two more issues to point out: Flow's library definition for Object.entries looks like this (from core.js):

```<code>declare class Object {
    /* ... */
    static entries(object: any): Array<[string, mixed]>;
    /* ... */
}
</code>```

Flow assumes that the type of values returned by Object.entries will be mixed, but that type should be V. The fix for this is to get values via object property access in a loop.

The type of the key argument to the given callback should be K, but Flow knows that in the array case that type will actually be number, and in the plain object case it will be string. A couple more type casts are necessary to fix those cases.

Finally, map:

```<code>function map<K, A, B, M: MyIterable<K, A>>(
  obj: M, fn: (value: A, key: K, obj: M) => B
): MyIterable<K, B> {
  const result = instantiateSameType( obj );
  forEach(obj, (value, key)=>{
    set( result, key, fn(value, key, this) );
  });
  return result;
}
</code>```

Some things that I want to point out here: the input collection has a type variable A while the output collection has the variable B. This is because map might change the type of values. And I set up a type variable M for the type of the input collection; that is to inform Flow that the type of the callback argument obj is the same as the type of the input collection. That allows you to use functions in your callback that are particular to the specific collection type that you provided when invoking map.

Title: Generic, higher order functions

Body:
I'm trying to add Flow type information to a small library of mine.

The library defines some functions that are generic over Object, Array, Set, Map and other types.

Here a small piece example to give an idea:

function set( obj, key, value ) {
  if( isMap(obj) )      { obj.set(key, value); }
  else if( isSet(obj) ) { obj.add(value);      }
  else                  { obj[key] = value;    }
}
function instantiateSameType( obj ) {
  if( isArray(obj) )    { return [];        }
  else if( isMap(obj) ) { return new Map(); }
  else if( isSet(obj) ) { return new Set(); }
  else                  { return {};        }
}
function forEach( obj, fn ) {
  if( obj.forEach ) obj.forEach(    ( value, key )=>fn(value, key, obj) );
  else Object.entries(obj).forEach( ([key, value])=>fn(value, key, obj) );
}
function map( obj, fn ) {
  const result = instantiateSameType( obj );
  forEach(obj, (value, key)=>{
    set( result, key, fn(value, key, this) );
  });
  return result;
}

How can I define types for map?

I'd want to avoid giving a specialized version for each of the 4 types I listed in the example, as map is generic over them.
I feel the need to define higher-order interfaces, and implement them for existing types, but can't find much about any of this...

Any hints or ideas?

Body:
I wanted to follow up with another answer that matches up with the question that you actually asked. Flow can do just what you want. But it does get a bit painful implementing functions that operate on all four of those collection types because in the case of Map the type for keys is fully generic, but for Array the key type must be number, and due to the way objects are implemented in Javascript the key type for Object is always effectively string. (Set does not have keys, but that does not matter too much because you do not need to use keys to set values in a Set.) The safest way to work around the Array and Object special cases would be to provide an overloaded type signature for every function. But it turns out to be quite difficult to tell Flow that key might be the fully-generic type K or string or number depending on the type of obj. The most practical option is to make each function fully generic in the key type. But you have to remember that these functions will fail if you try to use arrays or plain objects with the wrong key type, and you will not get a type error in those cases.

Let's start with a type for the set of collection types that you are working with:

type MyIterable<K, V> = Map<K, V> | Set<V> | Array<V> | Pojo<V>
type Pojo<V> = { [key: string]: V } // plain object

The collection types must all be listed at this point. If you want to work with an open set of collection types instead then see my other answer. And note that my other answer avoids the type-safety holes in the solution here.

There is a handy trick with Flow: you can put the keyword %checks in the type signature of a function that returns a boolean, and  Flow will be able to use invocations of that function at type-checking time for type refinements. But the body of the function must use constructions that Flow knows how to use for type refinements because Flow does not actually run the function at type-checking time. For example:

function isMap ( obj: any ): boolean %checks {
  return obj instanceof Map
}

function isSet ( obj: any ): boolean %checks {
  return obj instanceof Set
}

function isArray ( obj: any ): boolean %checks {
  return obj instanceof Array
}

I mentioned you would need a couple of type casts. One instance is in set: Flow knows that when assigning to an array index, the index variable should be a number, and it also knows that K might not be number. The same goes for assigning to plain object properties, since the Pojo type alias specifies string keys. So in the code branch for those cases you need to type-cast key to any, which effectively disables type checking for that use of key.

function set<K, V>( obj: MyIterable<K, V>, key: K, value: V ) {
  if( isMap(obj) )      { obj.set(key, value);    }
  else if( isSet(obj) ) { obj.add(value);         }
  else                  { obj[(key:any)] = value; }
}

Your instantiateSameType function just needs a type signature. An important point to keep in mind is that you use instantiateSameType to construct the result of map, and the type of values in the collection can change between the input and output when using map. So it is important to use two different type variables for the value type in the input and output of instantiateSameType as well. You might also allow instantiateSameType to change the key type; but that is not required to make map work correctly.

function instantiateSameType<K, A, B>( obj: MyIterable<K, A> ): MyIterable<K, B> {
  if( isArray(obj) )    { return [];        }
  else if( isMap(obj) ) { return new Map(); }
  else if( isSet(obj) ) { return new Set(); }
  else                  { return {};        }
}

That means that the output of instantiateSameType can hold any of values. It might be the same type as values in the input collection, or it might not.

In your implementation of forEach you check for the presence of obj.forEach as a type refinement. This is confusing to Flow because one of the types that make up MyIterable is a plain Javascript object, which might hold any string key. Flow cannot assume that obj.forEach will be falsy. So you need to use a different check. Re-using the isArray, etc. predicates works well:

function forEach<K, V, M: MyIterable<K, V>>( obj: M, fn: (value: V, key: K, obj: M) => any ) {
  if( isArray(obj) || isMap(obj) || isSet(obj) ) {
    obj.forEach((value, key) => fn(value, (key:any), obj));
  } else {
    for (const key of Object.keys(obj)) {
      fn(obj[key], (key:any), obj)
    }
  }
}

There are two more issues to point out: Flow's library definition for Object.entries looks like this (from core.js):

declare class Object {
    /* ... */
    static entries(object: any): Array<[string, mixed]>;
    /* ... */
}

Flow assumes that the type of values returned by Object.entries will be mixed, but that type should be V. The fix for this is to get values via object property access in a loop.

The type of the key argument to the given callback should be K, but Flow knows that in the array case that type will actually be number, and in the plain object case it will be string. A couple more type casts are necessary to fix those cases.

Finally, map:

function map<K, A, B, M: MyIterable<K, A>>(
  obj: M, fn: (value: A, key: K, obj: M) => B
): MyIterable<K, B> {
  const result = instantiateSameType( obj );
  forEach(obj, (value, key)=>{
    set( result, key, fn(value, key, this) );
  });
  return result;
}

Some things that I want to point out here: the input collection has a type variable A while the output collection has the variable B. This is because map might change the type of values. And I set up a type variable M for the type of the input collection; that is to inform Flow that the type of the callback argument obj is the same as the type of the input collection. That allows you to use functions in your callback that are particular to the specific collection type that you provided when invoking map.


问:
Nodes and edges overlap each other
I'm trying to visualize a graph (using JanusGraph) in Gephi, but all nodes and edges overlap each other in the "Preview" tab.

Using Gremlin I'm connecting to the db and create two vertices with one edge:

```<code>gremlin> graph = JanusGraphFactory.build().set("storage.backend", "cassandra").set("storage.hostname", "127.0.0.1").open();
==>standardjanusgraph[cassandra:[127.0.0.1]]
gremlin> v1 = graph.addVertex('human');
==>v[122896568]
gremlin> v2 = graph.addVertex('robot');
==>v[40976424]
gremlin> battle = v1.addEdge('battled', v2, 'time', 22);
==>e[215vyv-2163lk-8ufp-oe9m0][122896568-battled->40976424]
</code>```

Using graph streaming plugin I'm connecting to Gephi and submit the graph:

```<code>gremlin> :plugin use tinkerpop.gephi
==>tinkerpop.gephi activated
gremlin> :remote connect tinkerpop.gephi
==>Connection to Gephi - http://localhost:8080/workspace1 with stepDelay:1000, startRGBColor:[0.0, 1.0, 0.5], colorToFade:g, colorFadeRate:0.7, startSize:10.0,sizeDecrementRate:0.33
gremlin> :> graph
</code>```

In Gephi I see correct data in the "Data Laboratory" tab, but here is the result from the "Preview" tab:

I'm using:

```<code>Gephi v 0.9.2
Graph Streaming Plugin v 1.0.3
JanusGraph v 0.2.0
Gremlin v 3.2.6
</code>```

Using Titan the result was correct. What could be done to fix that for JanusGraph?

答:
… all nodes and edges overlap each other in the "Preview" tab.

Apply a layout algorithm:

Overview > Layout > [layout-algorithm's_name] > Run

Title: Nodes and edges overlap each other

Body:
I'm trying to visualize a graph (using JanusGraph) in Gephi, but all nodes and edges overlap each other in the "Preview" tab.

Using Gremlin I'm connecting to the db and create two vertices with one edge:

gremlin> graph = JanusGraphFactory.build().set("storage.backend", "cassandra").set("storage.hostname", "127.0.0.1").open();
==>standardjanusgraph[cassandra:[127.0.0.1]]
gremlin> v1 = graph.addVertex('human');
==>v[122896568]
gremlin> v2 = graph.addVertex('robot');
==>v[40976424]
gremlin> battle = v1.addEdge('battled', v2, 'time', 22);
==>e[215vyv-2163lk-8ufp-oe9m0][122896568-battled->40976424]

Using graph streaming plugin I'm connecting to Gephi and submit the graph:

gremlin> :plugin use tinkerpop.gephi
==>tinkerpop.gephi activated
gremlin> :remote connect tinkerpop.gephi
==>Connection to Gephi - http://localhost:8080/workspace1 with stepDelay:1000, startRGBColor:[0.0, 1.0, 0.5], colorToFade:g, colorFadeRate:0.7, startSize:10.0,sizeDecrementRate:0.33
gremlin> :> graph

In Gephi I see correct data in the "Data Laboratory" tab, but here is the result from the "Preview" tab:

I'm using:

Gephi v 0.9.2
Graph Streaming Plugin v 1.0.3
JanusGraph v 0.2.0
Gremlin v 3.2.6

Using Titan the result was correct. What could be done to fix that for JanusGraph?


问:
Unmirroring OpenTok video Input
I am using OpenTok for video conferencing in my app. I want to un-mirror my publisher video so that the person at other end can read text (as right now its a mirror image). OpenTok playground provides this feature but I am unable to find sample code for the same.</p>

答:
As the comment states, subscribers should always see the video the right way around. Only the publisher's video is mirrored so they can see themselves in a natural way. If you want the publisher's video not to be mirrored then initialise the publisher like this:

```<code>const publisher = OT.initPublisher({ mirror: false });
</code>```

Please see documentation for the mirror property here: https://tokbox.com/developer/sdks/js/reference/OT.html#initPublisher

Title: Unmirroring OpenTok video Input

Body:
As the comment states, subscribers should always see the video the right way around. Only the publisher's video is mirrored so they can see themselves in a natural way. If you want the publisher's video not to be mirrored then initialise the publisher like this:

const publisher = OT.initPublisher({ mirror: false });

Please see documentation for the mirror property here: https://tokbox.com/developer/sdks/js/reference/OT.html#initPublisher


问:
kableExtra only works if there's another table in the presentation?
When I use kableExtra for a PDF output, the table renders beautifully, BUT gives an error if there isn't another, non-kable extra table in the program. Has anyone else seen this behavior? the file appears to knit fine, but then throws an error in pandoc?

For example, this code:

```<code>---
output:
  beamer_presentation:
fontsize: 10pt
---

```{r global_options, include=FALSE}
library(rmarkdown)
library(knitr)
library(kableExtra)

```
### Slide with table
```{r echo=FALSE, warning=FALSE, message=FALSE}
df=mtcars[1:8,1:3]
kable(df,format="latex",booktabs=T,row.names=F) %>%
    row_spec(6, color = "red")
```
</code>```

Gives this error

```<code>processing file: t.rmd
List of 1
 $ include: logi FALSE

  |.......................................                          |  60%
  ordinary text without R code

  |....................................................             |  80%
label: unnamed-chunk-1 (with options)
List of 3
 $ echo   : logi FALSE
 $ warning: logi FALSE
 $ message: logi FALSE

  |.................................................................| 100%
  ordinary text without R code

"C:/PROGRA~2/Pandoc/pandoc" +RTS -K512m -RTS t.utf8.md --to beamer --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output t.pdf --highlight-style tango --latex-engine pdflatex
output file: t.knit.md

! Undefined control sequence.
\beamer@doifinframe ...in {tabular}{rrr} \toprule
                                                  mpg & cyl & disp\\ \midrul...
l.86 \end{frame}

pandoc.exe: Error producing PDF
Error: pandoc document conversion failed with error 43
In addition: Warning message:
running command '"C:/PROGRA~2/Pandoc/pandoc" +RTS -K512m -RTS t.utf8.md --to beamer --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output t.pdf --highlight-style tango --latex-engine pdflatex' had status 43
Execution halted
</code>```

But if I add one more slide with a dummy table, it prints beautifully:

```<code>---
output:
  beamer_presentation:
fontsize: 10pt
---

```{r global_options, include=FALSE}
library(rmarkdown)
library(knitr)
library(kableExtra)
```
### Slide with table
```{r echo=FALSE, warning=FALSE, message=FALSE}
df=mtcars[1:8,1:3]
kable(df,format="latex",booktabs=T,row.names=F) %>%
        row_spec(6, color = "red")
```
### Non-kableExtra table needed for some reason?
```{r echo=FALSE}
kable(df)
```
</code>```

Has anyone else seen this behavior? Any workarounds besides "put a dummy table as the last slide?"

答:
Beamer slides does not allow kableExtra to load latex packages automatically as it does in regular pdf document. You saw that error message from LaTeX because booktabs was not loaded. When you put an normal markdown table, some magic in rmarkdown pandoc template will load booktabs & longtable automatically, that's why the error was gone.

You can follow the documentation in the Getting Started section of the kableExtra documentation and put

```<code>header-includes:
- \usepackage{booktabs}
- \usepackage{longtable}
- \usepackage{array}
- \usepackage{multirow}
- \usepackage{wrapfig}
- \usepackage{float}
- \usepackage{colortbl}
- \usepackage{pdflscape}
- \usepackage{tabu}
- \usepackage{threeparttable}
</code>```

Note that I removed - \usepackage[table]{xcolor} from the list because beamer loaded xcolor with a different option settings.

Body:
When I use kableExtra for a PDF output, the table renders beautifully, BUT gives an error if there isn't another, non-kable extra table in the program. Has anyone else seen this behavior? the file appears to knit fine, but then throws an error in pandoc?

For example, this code:

---
output:
  beamer_presentation:
fontsize: 10pt
---

```{r global_options, include=FALSE}
library(rmarkdown)
library(knitr)
library(kableExtra)

```
### Slide with table
```{r echo=FALSE, warning=FALSE, message=FALSE}
df=mtcars[1:8,1:3]
kable(df,format="latex",booktabs=T,row.names=F) %>%
    row_spec(6, color = "red")
```

Gives this error

processing file: t.rmd
List of 1
 $ include: logi FALSE

  |.......................................                          |  60%
  ordinary text without R code

  |....................................................             |  80%
label: unnamed-chunk-1 (with options)
List of 3
 $ echo   : logi FALSE
 $ warning: logi FALSE
 $ message: logi FALSE

  |.................................................................| 100%
  ordinary text without R code

"C:/PROGRA~2/Pandoc/pandoc" +RTS -K512m -RTS t.utf8.md --to beamer --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output t.pdf --highlight-style tango --latex-engine pdflatex
output file: t.knit.md

! Undefined control sequence.
\beamer@doifinframe ...in {tabular}{rrr} \toprule
                                                  mpg & cyl & disp\\ \midrul...
l.86 \end{frame}

pandoc.exe: Error producing PDF
Error: pandoc document conversion failed with error 43
In addition: Warning message:
running command '"C:/PROGRA~2/Pandoc/pandoc" +RTS -K512m -RTS t.utf8.md --to beamer --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output t.pdf --highlight-style tango --latex-engine pdflatex' had status 43
Execution halted

But if I add one more slide with a dummy table, it prints beautifully:

---
output:
  beamer_presentation:
fontsize: 10pt
---

```{r global_options, include=FALSE}
library(rmarkdown)
library(knitr)
library(kableExtra)
```
### Slide with table
```{r echo=FALSE, warning=FALSE, message=FALSE}
df=mtcars[1:8,1:3]
kable(df,format="latex",booktabs=T,row.names=F) %>%
        row_spec(6, color = "red")
```
### Non-kableExtra table needed for some reason?
```{r echo=FALSE}
kable(df)
```

Has anyone else seen this behavior? Any workarounds besides "put a dummy table as the last slide?"

Body:
Beamer slides does not allow kableExtra to load latex packages automatically as it does in regular pdf document. You saw that error message from LaTeX because booktabs was not loaded. When you put an normal markdown table, some magic in rmarkdown pandoc template will load booktabs & longtable automatically, that's why the error was gone.

You can follow the documentation in the Getting Started section of the kableExtra documentation and put

header-includes:
- \usepackage{booktabs}
- \usepackage{longtable}
- \usepackage{array}
- \usepackage{multirow}
- \usepackage{wrapfig}
- \usepackage{float}
- \usepackage{colortbl}
- \usepackage{pdflscape}
- \usepackage{tabu}
- \usepackage{threeparttable}

Note that I removed - \usepackage[table]{xcolor} from the list because beamer loaded xcolor with a different option settings.


问:
Adding Multiple Filters to Pivot Tables
I'm trying to learn about pivot tables and ran into some useful sample data to test my knowledge, especially in A/B testing.

I have about 20,000 data sets like the above table. I want to use a pivot table to see filter certain parameters, kind of like an A/B test.

Lets say I implemented some changes to an audience, selected by:

Odd Number user ID

Date of Registration after September 30th, 2017

only IOS and NOT Android with App version after 5.

I want to see if people under the above filters bought our feature ("Yes" or "No") and compare it to the people that this specific feature wasn't rolled out to and see if the feature had some impact.

Using Pivot Tables, I'd be nice to measure this, filtering out the people that fit the criteria versus the people that don't, and see if the sum of feature bought has some difference.

Is Pivot Table the right idea to measure this? Can someone provide some help on how I can approach this?

I guess assuming this is a pivot table, the flexibility to see if the user's bitcoin or the specific phone model had impact could be useful too.

Thanks!

答:
Yes, a Pivot Table is a good way to tackle this. The cool thing about PivotTables is that they are easy to copy. So whip one up, put the UserID in the Values area, change the aggregation to Count, and then make multiple copies of the PivotTable. Then go make changes to different filters, and compare the counts.

Plenty of PivotTable tutorial on YouTube. Suggest you add "Mike Girvin" or "ExcelIsFun" to your google search terms, as Mike has hundreds of great videos on YouTube.

Title: Adding Multiple Filters to Pivot Tables


问:
Save Button on a Table in Javascript Not Working
I have this javascript which will allow a user to hit the edit button on a table and edit the content. They can then press save to save the new input. I want to do 4 things which I don't know how to do.

I want to remove the border from the input box after the edit button has been pressed and then the save button is pressed.

Once the save button is pressed I want the Edit, Save, and Delete Button to go back to the same format they were at before pressing Edit.

I want the select picker to be read only when the edit button has not been clicked.

Instead of Having the words "Edit","Save" and "Delete" I want to use font awesome icons.

I have uploaded the JS, CSS, and HTML code here.

function edit_row(no) {
  document.getElementById("edit_button" + no).style.display = "none";
  document.getElementById("save_button" + no).style.display = "block";

  var chore = document.getElementById("chore_row" + no);
  var duration = document.getElementById("duration_row" + no);

  var chore_data = chore.innerHTML;
  var duration_data = duration.innerHTML;

  chore.innerHTML = "<input type='text' id='chore_text" + no + "' value='" + chore_data + "'>";
  duration.innerHTML = "<input type='text' id='duration_text" + no + "' value='" + duration_data + "'>";
}

function save_row(no) {
  var chore_val = document.getElementById("chore_text" + no).value;
  var duration_val = document.getElementById("duration_text" + no).value;
  var rotation_val = document.getElementById("rotation_text" + no).value;

  document.getElementById("chore_row" + no).innerHTML = chore_val;
  document.getElementById("duration_row" + no).innerHTML = duration_val;
  document.getElementById("rotation_row" + no).innerHTML = rotation_val;

  document.getElementById("edit_button" + no).style.display = "block";
  document.getElementById("save_button" + no).style.display = "none";

}

function delete_row(no) {
  document.getElementById("row" + no + "").outerHTML = "";
}

function add_row() {
  var new_chore = document.getElementById("new_chore").value;
  var new_duration = document.getElementById("new_duration").value;

  var table = document.getElementById("ChoreTbl");
  var table_len = (table.rows.length) - 1;
  var row = table.insertRow(table_len).outerHTML = "" +
    "
" +
    "   " + new_chore + "	" +
    "   " + new_duration + "	" +
    "   " +
    "<select class='selectpicker1'>" +
    "<option>Daily</option>" +
    "<option>Weekly</option>" +
    "<option>Monthly</option>" +
    "</select>" +
    "	" +
    "   <input type='button' id='edit_button" + table_len + "' value='Edit' class='edit pageButton' onclick='edit_row(" + table_len + ")'> " +
    "       <input type='button' id='save_button" + table_len + "' value='Save' class='save pageButton' onclick='save_row(" + table_len + ")'> " +
    "       <input type='button' value='Delete' class='delete pageButton' onclick='delete_row(" + table_len + ")'>" +
    "   	" +
    "
";

  document.getElementById("new_chore").value = "";
  document.getElementById("new_duration").value = "";
  document.getElementById("new_rotation").value = "";
}```
<pre class="snippet-code-css lang-css prettyprint-override"><code>input {
  background-color: #fff1d9;
  border: solid;
  border-color: #fea680;
}

.pageButton {
  border: none;
}</code>```

Chore Setting

        Chore
        Time Frame to Complete
        Rotation Cycle

        Wash Floor
        3 days

          <select class="selectpicker1">
            <option>Daily</option>
            <option>Weekly</option>
            <option>Monthly</option>
          </select>

          <input type="button" id="edit_button1" value="Edit" class="edit pageButton" onclick="edit_row('1')">
          <input type="button" id="save_button1" value="Save" class="save pageButton" onclick="save_row('1')">
          <input type="button" value="Delete" class="delete pageButton" onclick="delete_row('1')">

        <input type="text" id="new_chore">
        <input type="text" id="new_duration">

          <select class="selectpicker1">
            <option>Daily</option>
            <option>Weekly</option>
            <option>Monthly</option>
          </select>

        <input type="button" class="add pageButton" onclick="add_row();" value="Add Chore">

```

答:
Here you go you can use the following.

$(document).ready(function() {
  $("select").attr('disabled', true);
});

function edit_row(no) {
  $("select").attr("disabled", false);
  $("edit_button" + no).show();
  $("save_button" + no).show();

  //document.getElementById("edit_button"+no).style.display="none";
  //document.getElementById("save_button"+no).style.display="block";

  var chore = document.getElementById("chore_row" + no);
  var duration = document.getElementById("duration_row" + no);

  var chore_data = chore.innerHTML;
  var duration_data = duration.innerHTML;

  chore.innerHTML = "<input type='text' id='chore_text" + no + "' value='" + chore_data + "'>";
  duration.innerHTML = "<input type='text' id='duration_text" + no + "' value='" + duration_data + "'>";
}

function save_row(no) {
  $("input[type='text']").css({
    border: 0
  });

  $("#edit_button" + no).show();

  var chore_val = $("chore_text" + no).value;

  var duration_val = $("#duration_text" + no).val();
  var rotation_val = $("#rotation_text" + no).val();

  $("#chore_row" + no).html(chore_val);
  $("#duration_row" + no).html(duration_val);
  $("#rotation_row" + no).html(rotation_val);

  $("#edit_button" + no).show();
  $("#save_button" + no).show();

}

function delete_row(no) {
  document.getElementById("row" + no + "").outerHTML = "";
}

function add_row() {
  var new_chore = document.getElementById("new_chore").value;
  var new_duration = document.getElementById("new_duration").value;

  var table = document.getElementById("ChoreTbl");
  var table_len = (table.rows.length) - 1;
  var row = table.insertRow(table_len).outerHTML = "" +
    "
" +
    "   " + new_chore + "	" +
    "   " + new_duration + "	" +
    "   " +
    "<select class='selectpicker1'>" +
    "<option>Daily</option>" +
    "<option>Weekly</option>" +
    "<option>Monthly</option>" +
    "</select>" +
    "	" +
    "   <input type='button' id='edit_button" + table_len + "' value='Edit' class='edit pageButton' onclick='edit_row(" + table_len + ")'> " +
    "       <input type='button' id='save_button" + table_len + "' value='Save' class='save pageButton' onclick='save_row(" + table_len + ")'> " +
    "       <input type='button' value='Delete' class='delete pageButton' onclick='delete_row(" + table_len + ")'>" +
    "   	" +
    "
";

  document.getElementById("new_chore").value = "";
  document.getElementById("new_duration").value = "";
  document.getElementById("new_rotation").value = "";
}```
</div>
</div>
</p>

<p>There are several errors in your code, so i revised it but the <code>chore_text</code> name input is not defined and i cant figure out why are you using it so i commented out the lines involved with that input, but the things you addressed are here you can see, just one thing I could not get your <code>2nd</code> point <strong>the buttons that you want to switch back to the previous layout</strong>. They never change or maybe I am not getting what you said, I have commented out the portions for you to fix that are buggy, but the problem you are concerned I have added the solution.</p>

<p><div class="snippet" data-lang="js" data-hide="true" data-console="true" data-babel="false">
<div class="snippet-code snippet-currently-hidden">
<pre class="snippet-code-js lang-js prettyprint-override"><code>$(document).ready(function() {
  $("select").attr('disabled', true);
});

function edit_row(no) {
  $("#selectpicker" + no).attr("disabled", false);

  $("#save_button" + no).show();

  var chore = $("#chore_row" + no);
  var duration = $("#duration_row" + no);

  var chore_data = chore.html();
  var duration_data = duration.html();

  chore.html("<input type='text' id='chore_text" + no + "' value='" + chore_data + "'>");
  duration.html("<input type='text' id='duration_text" + no + "' value='" + duration_data + "'>");
  $("input[type='text']").css({
    border: 0
  });
}

function save_row(no) {
  var chore_val = $("#chore_text" + no).val();
  var duration_val = $("#duration_text" + no).val();
  var rotation_val = $("#rotation_text" + no).val();

  $("#chore_row" + no).html(chore_val);
  $("#duration_row" + no).html(duration_val);
  $("#rotation_row" + no).html(rotation_val);

  $("#edit_button" + no).show();
  //$("#save_button" + no).hide();
  $("#selectpicker" + no).attr("disabled", true);
}

function delete_row(no) {
  //  $("#row" + no + "").clone().wrap('<p>').parent().html('');
  document.getElementById("row" + no + "").outerHTML = "";

}

function add_row() {
  var new_chore = $("#new_chore").val();
  var new_duration = $("#new_duration").val();

  var table = document.getElementById("ChoreTbl");
  var table_len = (table.rows.length) - 1;
  var row = table.insertRow(table_len).outerHTML = "" +
    "<tr id='row" + table_len + "'>" +
    "   <td id='chore_row" + table_len + "'>" + new_chore + "</td>" +
    "   <td id='duration_row" + table_len + "'>" + new_duration + "</td>" +
    "   <td id='rotation_row" + table_len + "'>" +
    "<select disabled class='selectpicker1' id='selectpicker" + table_len + "'>" +
    "<option>Daily</option>" +
    "<option>Weekly</option>" +
    "<option>Monthly</option>" +
    "</select>" +
    "</td>" +
    "   <td><i id='edit_button" + table_len + "'  class='fa fa-pencil' onclick='edit_row(" + table_len + ")'></i> " +
    "       <i id='save_button" + table_len + "' class='fa fa-floppy-o' onclick='save_row(" + table_len + ")'></i> " +
    "       <i class='fa fa-trash' onclick='delete_row(" + table_len + ")'></i>" +
    "   </td>" +
    "</tr>";

  $("#new_chore").val();
  $("#new_duration").val();
  //document.getElementById("new_rotation").value = "";
}</code>```

input {
  background-color: #fff1d9;
  border: solid;
  border-color: #fea680;
}

.pageButton {
  border: none;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="Chores">
  <table id="ChoreTbl" class="choreHead">
    <h1><b>Chore Setting</b></h1>

    <thead>
      <tr class="header" style="color:#008f95;">
        <td id="name_row2"><b>Chore</b></td>
        <td id="country_row2"><b>Time Frame to Complete</b></td>
        <td id="age_row2"><b>Rotation Cycle</b></td>
        <td></td>
    </thead>
    <tbody>
      <tr id="row1">
        <td id="chore_row1">Wash Floor</td>
        <td id="duration_row1">3 days</td>
        <td id="rotation_row1">
          <select class="selectpicker1" id="selectpicker1">
            <option>Daily</option>
            <option>Weekly</option>
            <option>Monthly</option>
          </select>
        </td>
        <td>
          <i id="edit_button1" class="fa fa-pencil" onclick="edit_row('1')"></i>
          <i id="save_button1" class="fa fa-floppy-o" onclick="save_row('1')"></i>
          <i class="fa fa-trash" onclick="delete_row('1')"></i>
        </td>
      </tr>
      <tr>
        <td><input type="text" id="new_chore"></td>
        <td><input type="text" id="new_duration"></td>
        <td>
          <select class="selectpicker1">
            <option>Daily</option>
            <option>Weekly</option>
            <option>Monthly</option>
          </select>
        </td>
        <td><input type="button" class="add pageButton" onclick="add_row();" value="Add Chore"></td>
      </tr>
    </tbody>
  </table></code>```

ContentLicense: CC BY-SA 4.0

Body:
I have this javascript which will allow a user to hit the edit button on a table and edit the content. They can then press save to save the new input. I want to do 4 things which I don't know how to do.

I want to remove the border from the input box after the edit button has been pressed and then the save button is pressed.

Once the save button is pressed I want the Edit, Save, and Delete Button to go back to the same format they were at before pressing Edit.

I want the select picker to be read only when the edit button has not been clicked.

Instead of Having the words "Edit","Save" and "Delete" I want to use font awesome icons.

I have uploaded the JS, CSS, and HTML code here.

function edit_row(no) {
  document.getElementById("edit_button" + no).style.display = "none";
  document.getElementById("save_button" + no).style.display = "block";

  var chore = document.getElementById("chore_row" + no);
  var duration = document.getElementById("duration_row" + no);

  var chore_data = chore.innerHTML;
  var duration_data = duration.innerHTML;

  chore.innerHTML = "<input type='text' id='chore_text" + no + "' value='" + chore_data + "'>";
  duration.innerHTML = "<input type='text' id='duration_text" + no + "' value='" + duration_data + "'>";
}

function save_row(no) {
  var chore_val = document.getElementById("chore_text" + no).value;
  var duration_val = document.getElementById("duration_text" + no).value;
  var rotation_val = document.getElementById("rotation_text" + no).value;

  document.getElementById("chore_row" + no).innerHTML = chore_val;
  document.getElementById("duration_row" + no).innerHTML = duration_val;
  document.getElementById("rotation_row" + no).innerHTML = rotation_val;

  document.getElementById("edit_button" + no).style.display = "block";
  document.getElementById("save_button" + no).style.display = "none";

}

function delete_row(no) {
  document.getElementById("row" + no + "").outerHTML = "";
}

function add_row() {
  var new_chore = document.getElementById("new_chore").value;
  var new_duration = document.getElementById("new_duration").value;

  var table = document.getElementById("ChoreTbl");
  var table_len = (table.rows.length) - 1;
  var row = table.insertRow(table_len).outerHTML = "" +
    "
" +
    "   " + new_chore + "	" +
    "   " + new_duration + "	" +
    "   " +
    "<select class='selectpicker1'>" +
    "<option>Daily</option>" +
    "<option>Weekly</option>" +
    "<option>Monthly</option>" +
    "</select>" +
    "	" +
    "   <input type='button' id='edit_button" + table_len + "' value='Edit' class='edit pageButton' onclick='edit_row(" + table_len + ")'> " +
    "       <input type='button' id='save_button" + table_len + "' value='Save' class='save pageButton' onclick='save_row(" + table_len + ")'> " +
    "       <input type='button' value='Delete' class='delete pageButton' onclick='delete_row(" + table_len + ")'>" +
    "   	" +
    "
";

  document.getElementById("new_chore").value = "";
  document.getElementById("new_duration").value = "";
  document.getElementById("new_rotation").value = "";
}

input {
  background-color: #fff1d9;
  border: solid;
  border-color: #fea680;
}

.pageButton {
  border: none;
}

Chore Setting

        Chore
        Time Frame to Complete
        Rotation Cycle

        Wash Floor
        3 days

          <select class="selectpicker1">
            <option>Daily</option>
            <option>Weekly</option>
            <option>Monthly</option>
          </select>

          <input type="button" id="edit_button1" value="Edit" class="edit pageButton" onclick="edit_row('1')">
          <input type="button" id="save_button1" value="Save" class="save pageButton" onclick="save_row('1')">
          <input type="button" value="Delete" class="delete pageButton" onclick="delete_row('1')">

        <input type="text" id="new_chore">
        <input type="text" id="new_duration">

          <select class="selectpicker1">
            <option>Daily</option>
            <option>Weekly</option>
            <option>Monthly</option>
          </select>

        <input type="button" class="add pageButton" onclick="add_row();" value="Add Chore">

Body:
Here you go you can use the following.

$(document).ready(function() {
  $("select").attr('disabled', true);
});

function edit_row(no) {
  $("select").attr("disabled", false);
  $("edit_button" + no).show();
  $("save_button" + no).show();

  //document.getElementById("edit_button"+no).style.display="none";
  //document.getElementById("save_button"+no).style.display="block";

  var chore = document.getElementById("chore_row" + no);
  var duration = document.getElementById("duration_row" + no);

  var chore_data = chore.innerHTML;
  var duration_data = duration.innerHTML;

  chore.innerHTML = "<input type='text' id='chore_text" + no + "' value='" + chore_data + "'>";
  duration.innerHTML = "<input type='text' id='duration_text" + no + "' value='" + duration_data + "'>";
}

function save_row(no) {
  $("input[type='text']").css({
    border: 0
  });

  $("#edit_button" + no).show();

  var chore_val = $("chore_text" + no).value;

  var duration_val = $("#duration_text" + no).val();
  var rotation_val = $("#rotation_text" + no).val();

  $("#chore_row" + no).html(chore_val);
  $("#duration_row" + no).html(duration_val);
  $("#rotation_row" + no).html(rotation_val);

  $("#edit_button" + no).show();
  $("#save_button" + no).show();

}

function delete_row(no) {
  document.getElementById("row" + no + "").outerHTML = "";
}

function add_row() {
  var new_chore = document.getElementById("new_chore").value;
  var new_duration = document.getElementById("new_duration").value;

  var table = document.getElementById("ChoreTbl");
  var table_len = (table.rows.length) - 1;
  var row = table.insertRow(table_len).outerHTML = "" +
    "<tr id='row" + table_len + "'>" +
    "   <td id='chore_row" + table_len + "'>" + new_chore + "</td>" +
    "   <td id='duration_row" + table_len + "'>" + new_duration + "</td>" +
    "   <td id='rotation_row'" + table_len + "'>" +
    "<select class='selectpicker1'>" +
    "<option>Daily</option>" +
    "<option>Weekly</option>" +
    "<option>Monthly</option>" +
    "</select>" +
    "</td>" +
    "   <td><input type='button' id='edit_button" + table_len + "' value='Edit' class='edit pageButton' onclick='edit_row(" + table_len + ")'> " +
    "       <input type='button' id='save_button" + table_len + "' value='Save' class='save pageButton' onclick='save_row(" + table_len + ")'> " +
    "       <input type='button' value='Delete' class='delete pageButton' onclick='delete_row(" + table_len + ")'>" +
    "   </td>" +
    "</tr>";

  document.getElementById("new_chore").value = "";
  document.getElementById("new_duration").value = "";
  document.getElementById("new_rotation").value = "";
}

There are several errors in your code, so i revised it but the chore_text name input is not defined and i cant figure out why are you using it so i commented out the lines involved with that input, but the things you addressed are here you can see, just one thing I could not get your 2nd point the buttons that you want to switch back to the previous layout. They never change or maybe I am not getting what you said, I have commented out the portions for you to fix that are buggy, but the problem you are concerned I have added the solution.

$(document).ready(function() {
  $("select").attr('disabled', true);
});

function edit_row(no) {
  $("#selectpicker" + no).attr("disabled", false);

  $("#save_button" + no).show();

  var chore = $("#chore_row" + no);
  var duration = $("#duration_row" + no);

  var chore_data = chore.html();
  var duration_data = duration.html();

  chore.html("<input type='text' id='chore_text" + no + "' value='" + chore_data + "'>");
  duration.html("<input type='text' id='duration_text" + no + "' value='" + duration_data + "'>");
  $("input[type='text']").css({
    border: 0
  });
}

function save_row(no) {
  var chore_val = $("#chore_text" + no).val();
  var duration_val = $("#duration_text" + no).val();
  var rotation_val = $("#rotation_text" + no).val();

  $("#chore_row" + no).html(chore_val);
  $("#duration_row" + no).html(duration_val);
  $("#rotation_row" + no).html(rotation_val);

  $("#edit_button" + no).show();
  //$("#save_button" + no).hide();
  $("#selectpicker" + no).attr("disabled", true);
}

function delete_row(no) {
  //  $("#row" + no + "").clone().wrap('<p>').parent().html('');
  document.getElementById("row" + no + "").outerHTML = "";

}

function add_row() {
  var new_chore = $("#new_chore").val();
  var new_duration = $("#new_duration").val();

  var table = document.getElementById("ChoreTbl");
  var table_len = (table.rows.length) - 1;
  var row = table.insertRow(table_len).outerHTML = "" +
    "<tr id='row" + table_len + "'>" +
    "   <td id='chore_row" + table_len + "'>" + new_chore + "</td>" +
    "   <td id='duration_row" + table_len + "'>" + new_duration + "</td>" +
    "   <td id='rotation_row" + table_len + "'>" +
    "<select disabled class='selectpicker1' id='selectpicker" + table_len + "'>" +
    "<option>Daily</option>" +
    "<option>Weekly</option>" +
    "<option>Monthly</option>" +
    "</select>" +
    "</td>" +
    "   <td><i id='edit_button" + table_len + "'  class='fa fa-pencil' onclick='edit_row(" + table_len + ")'></i> " +
    "       <i id='save_button" + table_len + "' class='fa fa-floppy-o' onclick='save_row(" + table_len + ")'></i> " +
    "       <i class='fa fa-trash' onclick='delete_row(" + table_len + ")'></i>" +
    "   </td>" +
    "</tr>";

  $("#new_chore").val();
  $("#new_duration").val();
  //document.getElementById("new_rotation").value = "";
}

input {
  background-color: #fff1d9;
  border: solid;
  border-color: #fea680;
}

.pageButton {
  border: none;
}

<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="Chores">
  <table id="ChoreTbl" class="choreHead">
    <h1><b>Chore Setting</b></h1>

    <thead>
      <tr class="header" style="color:#008f95;">
        <td id="name_row2"><b>Chore</b></td>
        <td id="country_row2"><b>Time Frame to Complete</b></td>
        <td id="age_row2"><b>Rotation Cycle</b></td>
        <td></td>
    </thead>
    <tbody>
      <tr id="row1">
        <td id="chore_row1">Wash Floor</td>
        <td id="duration_row1">3 days</td>
        <td id="rotation_row1">
          <select class="selectpicker1" id="selectpicker1">
            <option>Daily</option>
            <option>Weekly</option>
            <option>Monthly</option>
          </select>
        </td>
        <td>
          <i id="edit_button1" class="fa fa-pencil" onclick="edit_row('1')"></i>
          <i id="save_button1" class="fa fa-floppy-o" onclick="save_row('1')"></i>
          <i class="fa fa-trash" onclick="delete_row('1')"></i>
        </td>
      </tr>
      <tr>
        <td><input type="text" id="new_chore"></td>
        <td><input type="text" id="new_duration"></td>
        <td>
          <select class="selectpicker1">
            <option>Daily</option>
            <option>Weekly</option>
            <option>Monthly</option>
          </select>
        </td>
        <td><input type="button" class="add pageButton" onclick="add_row();" value="Add Chore"></td>
      </tr>
    </tbody>
  </table>


问:
How can I schedule an email to be sent at some point in the future in django?
I want to schedule an email to be sent to a user upon a specific action.
However, if the user takes another action I want to cancel that email and have it not send.

How would I do that in django or python?

答:
Beanstalkd

If you can install beanstalkd and run python script from command line I would use that to schedule emails. With beanstalkc client you can easily accomplish this. On ubuntu you might first need to install:

sudo apt-get install python-yaml python-setuptools

consumer.py:

import beanstalkc

```<code>def main():
    beanstalk = beanstalkc.Connection(host='localhost', port=11300)
    while True:
        job = beanstalk.reserve()
        print job.body
        job.delete()

if __name__ == '__main__':
    main()
</code>```

Will print job 5 seconds after it get's inserted by producer.py. Offcourse this should be set longer to when you want to schedule your emails, but for demonstration purposes it will do. You don't want to wait half an hour to schedule message when testing ;).

producer.py:

import beanstalkc

```<code>def main():
    beanstalk = beanstalkc.Connection(host='localhost', port=11300)
    jid = beanstalk.put('foo', delay=5)

if __name__ == '__main__':
    main()
</code>```

GAE Task Queue

You could also use Google App engine task queue to accomplish this. You can specify an eta for your Task. Google App engine has a generous free quota. In the task queue webhook make Asynchronous Requests to fetch URL on your server which does the sending of emails.

ContentLicense: CC BY-SA 2.5

Body:
Beanstalkd

If you can install beanstalkd and run python script from command line I would use that to schedule emails. With beanstalkc client you can easily accomplish this. On ubuntu you might first need to install:

sudo apt-get install python-yaml python-setuptools

consumer.py:

import beanstalkc

def main():
    beanstalk = beanstalkc.Connection(host='localhost', port=11300)
    while True:
        job = beanstalk.reserve()
        print job.body
        job.delete()

if __name__ == '__main__':
    main()

Will print job 5 seconds after it get's inserted by producer.py. Offcourse this should be set longer to when you want to schedule your emails, but for demonstration purposes it will do. You don't want to wait half an hour to schedule message when testing ;).

producer.py:

import beanstalkc

def main():
    beanstalk = beanstalkc.Connection(host='localhost', port=11300)
    jid = beanstalk.put('foo', delay=5)

if __name__ == '__main__':
    main()

GAE Task Queue

You could also use Google App engine task queue to accomplish this. You can specify an eta for your Task. Google App engine has a generous free quota. In the task queue webhook make Asynchronous Requests to fetch URL on your server which does the sending of emails.


问:
Django poll tutorial AttributeError
I've ran into problem with Django Poll tutorial. For some reason, I keep getting

AttributeError: 'Question' object has no attribute 'question_text'

I've been following tutorial step by step, not sure what went wrong.

Mmodels.py:

```<code>from django.db import models
import datetime
from django.utils import timezone

class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text
</code>```

答:
I guess fields are missing from you model definition. As per django tutorial that you are referring models looks like this.

```<code>class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text
</code>```

If you place these, you will not face that error.

Title: Django poll tutorial AttributeError

Body:
I've ran into problem with Django Poll tutorial. For some reason, I keep getting

AttributeError: 'Question' object has no attribute 'question_text'

I've been following tutorial step by step, not sure what went wrong.

Mmodels.py:

from django.db import models
import datetime
from django.utils import timezone

class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

Body:
I guess fields are missing from you model definition. As per django tutorial that you are referring models looks like this.

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):
        return self.question_text

    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text

If you place these, you will not face that error.


问:
Low Level Difference between git rebase, git rebase -i and git merge
During a rebase, where I synced my local feature branch to the upstream branch to finalize a pull request, I tried using all three methods (git rebase, git rebase -i and git merge) and each of them offered a completely different experience, when it came to conflict resolving.

Git merge showed me all my conflicts at once. I resolved them and added the changes once done solving all of them. As expected, merging messed up my history and I had to revert again.

Git Rebase led me through the conflicts in two steps. In each I added my changes and continued the rebase thereafter. In between I lost one of my patches and had to start over again.

Interactive Rebasing worked like a charm. It led me through the conflicts commit by commit, and after each resolution, it started fast forwarding again from the base of the feature branch to the next conflict. I could ensure that commit co-authors were included correctly and at the end did not even need to add a 'merge' or 'rebase' commit, sitting at the head of the branch after finishing.

I have a conceptual understanding of when to use each of them, but why exactly did the rebase and interactive rebase behave so wildly different, even without interactively editing the revision? Why are git merge and git rebase even used, when they seem to do things badly and make it easier to mess up something in the history?

答:
... why exactly did the rebase and interactive rebase behave so wildly different

As a general rule, they shouldn't.  They sometimes do, and explaining precisely why is tricky.  A quick bottom line take-away is that the non-interactive git rebase uses—well, sometimes uses—git format-patch and pipes its output to git am, and this can, though usually doesn't, do the same thing as the interactive rebase, which uses git cherry-pick instead.

Historically, this was the only form of git rebase, and since it does behave a bit differently—and could work better—the Git authors chose not to switch everyone to an "always cherry pick" approach.

The long and involved answer

Why are git merge and git rebase even used, when they seem to do things badly and make it easier to mess up something in the history?

First, git merge and git rebase have different goals, so they're not all that comparable.  You're already aware that Git is all about commits, with branch names merely a way to find a commit—one specific commit, from which Git finds all the previous commits—but let's do a bit of terminology here to help us talk about it:

```<code>...--o--*--o--L   <-- master (HEAD)
         \
          o--o--R   <-- develop
</code>```

Note that we can re-draw this as:

```<code>          o--L   <-- master (HEAD)
         /
...--o--*
         \
          o--o--R   <-- develop
</code>```

to emphasize that, from commit * on backwards, all these commits are on both branches simultaneously.  The name master, which is also the current branch HEAD, identifies commit L (for "left" or "local").  The name develop identifies commit R ("right" or "remote").  It's those two commits that identify their parent commits, and if we—or Git—carefully follow each parent backwards, the two streams of commits eventually rejoin—permanently, in this case—at commit *.

Notes on git merge, which we need to talk about rebase

Running git merge asks Git to find the merge base, i.e., commit *, and then compare that merge base to each of the two branch tip commits L (local or --ours) and R (remote or --theirs).  Whatever is different on the left/local side, we must have changed.  Whatever is different on the right/remote side, they must have changed.  The merge machinery, performing the act of merging ("merge" as a verb), combines these two sets of changes.

The git merge command (assuming it does a real merge like this, i.e., that you're not doing fast-forward or squash) uses the merge machinery in this way to compute the set of files that should be committed, then makes a new merge commit.  This kind of commit—which uses the word "merge" as an adjective, or is shortened to just "a merge", using "merge" as a noun—has two parents: L is the first parent, and R is the second.  The files are determined by the merge-as-a-verb action; the commit itself is a merge.  If we draw this as:

```<code>...--o--o--o--L---M   <-- master (HEAD)
         \       /
          o--o--R   <-- develop
</code>```

we can then add more commits later, at which point we can run git merge again, choosing a new L and R:

```<code>...--o--o--o--o---M--L   <-- master (HEAD)
         \       /
          o--o--o--o--R   <-- develop
</code>```

The merge base this time is not the commit that used to be *, but rather the commit that used to be R!  So the presence of merge commit M alters the next merge base for the next git merge command.

Basics of any rebase

What git rebase does is very different: it identifies some set of commits to copy, and then copies them.

The set of commits to copy is the commits that are reachable from the current branch (i.e., HEAD), that are not reachable from the <upstream> argument you supply:

```<code>$ git checkout develop
$ git rebase <upstream-hash>   # or, easier, git rebase master
</code>```

At this point, internally, Git generates a list of commit hashes.  If the commit graph still looks like this:

```<code>...--o--*--F--G   <-- master
         \
          C--D--E   <-- develop (HEAD)
</code>```

and the argument to git rebase identifies commit * or any commit after that on master—including, of course, G, the tip of master, which is usually what we would choose here—then the set of commit hashes to be copied are those for C--D--E.

Some commits in this set may be tossed out, on purpose.  This includes:

any merge commits at all, because they cannot be copied (but there are none here—mostly this would eliminate any merges from master back into develop);

any commit whose git patch-id matches that of an upstream commit.

The latter means that Git computes the git patch-id for commits F and G.  If those match the git patch-id of commits C, D, or E, those commits are tossed from the "to copy" list.

(If --fork-point mode is used, Git may toss additional commits from the list.  Describing this well is difficult.  See Git rebase - commit select in fork-point mode.)

Git now begins the copying process.  This is where non-interactive and interactive rebase can differ.  Both start by "detaching HEAD", setting it to the target of the copying.  This defaults to the <upstream> commit, in our case, commit G.

The normal non-interactive method

Normally, a non-interactive git rebase runs git format-patch on the selected commits, then feeds the output to git am:

```<code>git format-patch -k --stdout --full-index --cherry-pick --right-only \
        --src-prefix=a/ --dst-prefix=b/ --no-renames --no-cover-letter \
        $git_format_patch_opt \
        "$revisions" ${restrict_revision+^$restrict_revision} \
        >"$GIT_DIR/rebased-patches"
...
git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" \
        $allow_rerere_autoupdate \
        ${gpg_sign_opt:+"$gpg_sign_opt"} <"$GIT_DIR/rebased-patches"
</code>```

This git am repeatedly invokes git apply -3.  Each git apply tries to apply the diff directly: find the context, verify that the context is unchanged, and then add and delete the lines shown in the git diff output embedded in the git format-patch stream.

If the verification step fails, git apply -3 (the -3 is important) uses a fallback method: the index lines in the format-patch output identify the merge base version of each file, so git apply can extract that merge base version, apply the patch directly to it—this should always work—and use that as a "version R".  The merge base version is, of course, the merge base version, and the current or HEAD version of the file is acts as "version L".  We now have everything we need to do a regular git merge of that one particular file.  We only merge one file at this point, and this is just "merge as a verb".  (See also the description below of git cherry-pick.)

This three-way merge can succeed or fail as always.  Whichever happens, Git can move on to the rest of the files in this particular patch.  If all patches apply—either directly, or as a result of the three-way merge fallback—Git will make a commit from the result, using the message text saved in the git format-patch stream.  This copies the original commit to a new, but at least slightly different, commit, whose parent is the commit that was HEAD:

```<code>                C'   <-- HEAD
               /
...--o--*--F--G   <-- master
         \
          C--D--E   <-- develop
</code>```

This process repeats for commits D and E, giving:

```<code>                C'-D'-E'   <-- HEAD
               /
...--o--*--F--G   <-- master
         \
          C--D--E   <-- develop
</code>```

When it's complete, git rebase "peels the label" develop off the old commit chain and sticks it on the new one.  Ideally, the old commits are abandoned, find-able only through the reflogs and, temporarily, the special name ORIG_HEAD:

```<code>                C'-D'-E'   <-- develop (HEAD)
               /
...--o--*--F--G   <-- master
         \
          C--D--E   [abandoned]
</code>```

though if there are other ways to find the old commits (existing tag or branch names that lead to them), the old commits aren't abandoned after all, and you will see both old and new.

Interactive rebase

The obvious difference between old-style git-rebase--am.sh and interactive git-rebase--interactive.sh is that the latter writes a big instructions file including help text, and lets you edit it.  But even if you just write it out as is, the actual code to implement each pick command runs git cherry-pick.  (This code has been revised in the most recent versions of Git and is now implemented in C, rather than shell script, but the shell script is much clearer, and the two are supposed to behave the same, so I have linked to the script here.)

When git cherry-pick runs, it always does a three-way merge (at least in any even semi-modern Git: there may have been an old one that used git format-patch | git am -3, at some point; I have a fuzzy memory of different behavior in early days).  What's unusual about this three-way merge is that the merge base is the parent of the commit being cherry-picked.  This means that if we are about to copy commit D, as in this state:

```<code>          o--L   <-- master (HEAD)
         /
...--o--*
         \
          o--o--R   <-- develop
</code>```0

the merge base for this particular merge-as-a-verb operation is not commit *.  It's not even a commit that's on master at all: it's commit C.

The merge base when we were copying C to C' was *, since * is C's parent.  That one makes sense.  This one doesn't, at least at first.  How can C be the merge base?  But it is: Git runs git diff --find-renames C C' in order to see "what we changed", and combines that with git diff --find-renames C D ("what they changed").

If any of those changes overlap, we'll get a merge conflict.  If not, Git will keep "what we changed" and simply add to it "what they changed".  Note that these two comparisons, these two git diff --find-rename operations, run commit-wide, not just on one specific file.  This allows the cherry-pick to find files that were renamed in one of the two branches.  Git then does the merge-as-a-verb on every file.  When it is done, if there is no conflict, Git makes an ordinary (non-merge) commit from the resulting files.

Assuming all goes well, and D gets copied to D', Git goes on to cherry-pick E.  This time D is the merge base.  The action works just as before: we find renames, merge-as-a-verb all the files, and make an ordinary, non-merge commit that is E'.

Finally, as with non-interactive rebase, Git peels the branch name off the old tip commit and places it on the new tip.

More peculiarities of non-interactive vs interactive

There are a number of side consequences of non-interactive rebase using git format-patch.  The most significant is that git format-patch literally cannot produce an "empty" patch—a commit that makes no changes to the source—so if you use -k to "keep" such commits, the non-interactive rebase uses git cherry-pick.

The second is that because git format-patch is told --no-renames (see the actual command above), it represents a file rename as "delete old file, add new file".  This prevents Git from spotting some conflicts.  (As long as the to-be-deleted file is in the patch, it can at least detect a delete/modify conflict, but it can't detect a delete/rename conflict, and in patches "beyond" the rename, it will have nothing at all to notice.)  And, of course, if we can construct a case in which a patch applies because of apparently-valid context, even though a three-way merge might find that the matching context is from a moved copy of the code, we can successfully apply a patch where a three-way merge would either detect a conflict, or apply it elsewhere.

(I intend to construct an example at some point but have never had time to do it.)

If you use the -m option, specifying that rebase should use the merge machinery, or a -s <strategy> option or -X <extended-option> (both of which imply using the merge machinery), this also forces Git to use cherry-pick.  However, that's actually a third kind of rebase!

The rebase type-selection happens in git-rebase.sh, well into the script:

```<code>          o--L   <-- master (HEAD)
         /
...--o--*
         \
          o--o--R   <-- develop
</code>```1

Note that the location of hidden state files, keeping track of whether you're in the middle of an ongoing git rebase that has stopped to let you edit (interactive rebase) or due to a conflict (any rebase), varies depending on the type of rebase.

Git notes

The last point of difference is that the am based rebase does not run git notes copy.  The other two do.  This means that notes you made on the original commits are dropped when using git rebase, but kept when using interactive rebase or git rebase -m.

(This seems like a bug to me, but perhaps it is deliberate.  Preserving the notes would be a little tricky since we need a mapping from old commit hash to new commit hash.  This would need support inside git am.)

Body:
... why exactly did the rebase and interactive rebase behave so wildly different

As a general rule, they shouldn't.  They sometimes do, and explaining precisely why is tricky.  A quick bottom line take-away is that the non-interactive git rebase uses—well, sometimes uses—git format-patch and pipes its output to git am, and this can, though usually doesn't, do the same thing as the interactive rebase, which uses git cherry-pick instead.

Historically, this was the only form of git rebase, and since it does behave a bit differently—and could work better—the Git authors chose not to switch everyone to an "always cherry pick" approach.

The long and involved answer

Why are git merge and git rebase even used, when they seem to do things badly and make it easier to mess up something in the history?

First, git merge and git rebase have different goals, so they're not all that comparable.  You're already aware that Git is all about commits, with branch names merely a way to find a commit—one specific commit, from which Git finds all the previous commits—but let's do a bit of terminology here to help us talk about it:

...--o--*--o--L   <-- master (HEAD)
         \
          o--o--R   <-- develop

Note that we can re-draw this as:

          o--L   <-- master (HEAD)
         /
...--o--*
         \
          o--o--R   <-- develop

to emphasize that, from commit * on backwards, all these commits are on both branches simultaneously.  The name master, which is also the current branch HEAD, identifies commit L (for "left" or "local").  The name develop identifies commit R ("right" or "remote").  It's those two commits that identify their parent commits, and if we—or Git—carefully follow each parent backwards, the two streams of commits eventually rejoin—permanently, in this case—at commit *.

Notes on git merge, which we need to talk about rebase

Running git merge asks Git to find the merge base, i.e., commit *, and then compare that merge base to each of the two branch tip commits L (local or --ours) and R (remote or --theirs).  Whatever is different on the left/local side, we must have changed.  Whatever is different on the right/remote side, they must have changed.  The merge machinery, performing the act of merging ("merge" as a verb), combines these two sets of changes.

The git merge command (assuming it does a real merge like this, i.e., that you're not doing fast-forward or squash) uses the merge machinery in this way to compute the set of files that should be committed, then makes a new merge commit.  This kind of commit—which uses the word "merge" as an adjective, or is shortened to just "a merge", using "merge" as a noun—has two parents: L is the first parent, and R is the second.  The files are determined by the merge-as-a-verb action; the commit itself is a merge.  If we draw this as:

...--o--o--o--L---M   <-- master (HEAD)
         \       /
          o--o--R   <-- develop

we can then add more commits later, at which point we can run git merge again, choosing a new L and R:

...--o--o--o--o---M--L   <-- master (HEAD)
         \       /
          o--o--o--o--R   <-- develop

The merge base this time is not the commit that used to be *, but rather the commit that used to be R!  So the presence of merge commit M alters the next merge base for the next git merge command.

Basics of any rebase

What git rebase does is very different: it identifies some set of commits to copy, and then copies them.

The set of commits to copy is the commits that are reachable from the current branch (i.e., HEAD), that are not reachable from the <upstream> argument you supply:

$ git checkout develop
$ git rebase <upstream-hash>   # or, easier, git rebase master

At this point, internally, Git generates a list of commit hashes.  If the commit graph still looks like this:

...--o--*--F--G   <-- master
         \
          C--D--E   <-- develop (HEAD)

and the argument to git rebase identifies commit * or any commit after that on master—including, of course, G, the tip of master, which is usually what we would choose here—then the set of commit hashes to be copied are those for C--D--E.

Some commits in this set may be tossed out, on purpose.  This includes:

any merge commits at all, because they cannot be copied (but there are none here—mostly this would eliminate any merges from master back into develop);

any commit whose git patch-id matches that of an upstream commit.

The latter means that Git computes the git patch-id for commits F and G.  If those match the git patch-id of commits C, D, or E, those commits are tossed from the "to copy" list.

(If --fork-point mode is used, Git may toss additional commits from the list.  Describing this well is difficult.  See Git rebase - commit select in fork-point mode.)

Git now begins the copying process.  This is where non-interactive and interactive rebase can differ.  Both start by "detaching HEAD", setting it to the target of the copying.  This defaults to the <upstream> commit, in our case, commit G.

The normal non-interactive method

Normally, a non-interactive git rebase runs git format-patch on the selected commits, then feeds the output to git am:

git format-patch -k --stdout --full-index --cherry-pick --right-only \
        --src-prefix=a/ --dst-prefix=b/ --no-renames --no-cover-letter \
        $git_format_patch_opt \
        "$revisions" ${restrict_revision+^$restrict_revision} \
        >"$GIT_DIR/rebased-patches"
...
git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" \
        $allow_rerere_autoupdate \
        ${gpg_sign_opt:+"$gpg_sign_opt"} <"$GIT_DIR/rebased-patches"

This git am repeatedly invokes git apply -3.  Each git apply tries to apply the diff directly: find the context, verify that the context is unchanged, and then add and delete the lines shown in the git diff output embedded in the git format-patch stream.

If the verification step fails, git apply -3 (the -3 is important) uses a fallback method: the index lines in the format-patch output identify the merge base version of each file, so git apply can extract that merge base version, apply the patch directly to it—this should always work—and use that as a "version R".  The merge base version is, of course, the merge base version, and the current or HEAD version of the file is acts as "version L".  We now have everything we need to do a regular git merge of that one particular file.  We only merge one file at this point, and this is just "merge as a verb".  (See also the description below of git cherry-pick.)

This three-way merge can succeed or fail as always.  Whichever happens, Git can move on to the rest of the files in this particular patch.  If all patches apply—either directly, or as a result of the three-way merge fallback—Git will make a commit from the result, using the message text saved in the git format-patch stream.  This copies the original commit to a new, but at least slightly different, commit, whose parent is the commit that was HEAD:

                C'   <-- HEAD
               /
...--o--*--F--G   <-- master
         \
          C--D--E   <-- develop

This process repeats for commits D and E, giving:

                C'-D'-E'   <-- HEAD
               /
...--o--*--F--G   <-- master
         \
          C--D--E   <-- develop

When it's complete, git rebase "peels the label" develop off the old commit chain and sticks it on the new one.  Ideally, the old commits are abandoned, find-able only through the reflogs and, temporarily, the special name ORIG_HEAD:

                C'-D'-E'   <-- develop (HEAD)
               /
...--o--*--F--G   <-- master
         \
          C--D--E   [abandoned]

though if there are other ways to find the old commits (existing tag or branch names that lead to them), the old commits aren't abandoned after all, and you will see both old and new.

Interactive rebase

The obvious difference between old-style git-rebase--am.sh and interactive git-rebase--interactive.sh is that the latter writes a big instructions file including help text, and lets you edit it.  But even if you just write it out as is, the actual code to implement each pick command runs git cherry-pick.  (This code has been revised in the most recent versions of Git and is now implemented in C, rather than shell script, but the shell script is much clearer, and the two are supposed to behave the same, so I have linked to the script here.)

When git cherry-pick runs, it always does a three-way merge (at least in any even semi-modern Git: there may have been an old one that used git format-patch | git am -3, at some point; I have a fuzzy memory of different behavior in early days).  What's unusual about this three-way merge is that the merge base is the parent of the commit being cherry-picked.  This means that if we are about to copy commit D, as in this state:

                C'   <-- HEAD
               /
...--o--*--F--G   <-- master
         \
          C--D--E   <-- develop

the merge base for this particular merge-as-a-verb operation is not commit *.  It's not even a commit that's on master at all: it's commit C.

The merge base when we were copying C to C' was *, since * is C's parent.  That one makes sense.  This one doesn't, at least at first.  How can C be the merge base?  But it is: Git runs git diff --find-renames C C' in order to see "what we changed", and combines that with git diff --find-renames C D ("what they changed").

If any of those changes overlap, we'll get a merge conflict.  If not, Git will keep "what we changed" and simply add to it "what they changed".  Note that these two comparisons, these two git diff --find-rename operations, run commit-wide, not just on one specific file.  This allows the cherry-pick to find files that were renamed in one of the two branches.  Git then does the merge-as-a-verb on every file.  When it is done, if there is no conflict, Git makes an ordinary (non-merge) commit from the resulting files.

Assuming all goes well, and D gets copied to D', Git goes on to cherry-pick E.  This time D is the merge base.  The action works just as before: we find renames, merge-as-a-verb all the files, and make an ordinary, non-merge commit that is E'.

Finally, as with non-interactive rebase, Git peels the branch name off the old tip commit and places it on the new tip.

More peculiarities of non-interactive vs interactive

There are a number of side consequences of non-interactive rebase using git format-patch.  The most significant is that git format-patch literally cannot produce an "empty" patch—a commit that makes no changes to the source—so if you use -k to "keep" such commits, the non-interactive rebase uses git cherry-pick.

The second is that because git format-patch is told --no-renames (see the actual command above), it represents a file rename as "delete old file, add new file".  This prevents Git from spotting some conflicts.  (As long as the to-be-deleted file is in the patch, it can at least detect a delete/modify conflict, but it can't detect a delete/rename conflict, and in patches "beyond" the rename, it will have nothing at all to notice.)  And, of course, if we can construct a case in which a patch applies because of apparently-valid context, even though a three-way merge might find that the matching context is from a moved copy of the code, we can successfully apply a patch where a three-way merge would either detect a conflict, or apply it elsewhere.

(I intend to construct an example at some point but have never had time to do it.)

If you use the -m option, specifying that rebase should use the merge machinery, or a -s <strategy> option or -X <extended-option> (both of which imply using the merge machinery), this also forces Git to use cherry-pick.  However, that's actually a third kind of rebase!

The rebase type-selection happens in git-rebase.sh, well into the script:

if test -n "$interactive_rebase"
then
        type=interactive
        state_dir="$merge_dir"
elif test -n "$do_merge"
then
        type=merge
        state_dir="$merge_dir"
else
        type=am
        state_dir="$apply_dir"
fi

Note that the location of hidden state files, keeping track of whether you're in the middle of an ongoing git rebase that has stopped to let you edit (interactive rebase) or due to a conflict (any rebase), varies depending on the type of rebase.

Git notes

The last point of difference is that the am based rebase does not run git notes copy.  The other two do.  This means that notes you made on the original commits are dropped when using git rebase, but kept when using interactive rebase or git rebase -m.

(This seems like a bug to me, but perhaps it is deliberate.  Preserving the notes would be a little tricky since we need a mapping from old commit hash to new commit hash.  This would need support inside git am.)


问:
php remove from array if property value is in another array
I want to remove all elements from arr2 that have a type contained in arr1:

```<code>    arr1 = ['A', 'B', 'C']

    arr2 = [
        [
        'name' => 'jane',
        'type' => 'X'
        ],
        [
        'name' => 'jon',
        'type' => 'B'
        ]
    ]
</code>```

So jon should be removed. Is there some built in function like array_diff?

答:
Here's another if the type is unique:

```<code>$result = array_diff_key(array_column($arr2, null, 'type'), array_flip($arr1));
</code>```

extract an array from $arr2 keyed (indexed) by the type column

flip $arr1 to get values as keys

get the key differences

Run array_values on it to re-index if needed.

Body:
I want to remove all elements from arr2 that have a type contained in arr1:

    arr1 = ['A', 'B', 'C']

    arr2 = [
        [
        'name' => 'jane',
        'type' => 'X'
        ],
        [
        'name' => 'jon',
        'type' => 'B'
        ]
    ]

So jon should be removed. Is there some built in function like array_diff?

Body:
Here's another if the type is unique:

$result = array_diff_key(array_column($arr2, null, 'type'), array_flip($arr1));

extract an array from $arr2 keyed (indexed) by the type column

flip $arr1 to get values as keys

get the key differences

Run array_values on it to re-index if needed.


问:
Dereference works with ptr->operator*() but not with *ptr
I'm creating an iterator for a list class.  The iterator has a dereference operator:

```<code>    T& operator*() const {
        return this->currentNode->data;
    }
</code>```

While trying to use the iterator:

```<code>for( ; list->begin() != list->end; (*list_iter).operator++())
{
    cout << list_iter << endl;
    cout << list_iter->operator*() << endl;
    //cout << *list_iter << endl;  //not working
}
</code>```

The commented line says "invalid operand to binary experssion ostream and MyList::iterator".  Likewise, if I change from (*list_iter).operator++() to list_iter++ or (*list_iter)++, I get a similar error.

What I think is happening is something like this:

```<code>int num1 = 3;
int *num2 = new int;
*num2 = 3;
</code>```

In this case, num1 is == *num2...  *num2 is functionally similar to num1 (both are integers), though num2 is a pointer to an integer, the *num2 makes it an integer.

So in:

```<code>MyList list1();
MyList *list2 = new MyList();
</code>```

In this case, should I expect "*list2" to be similar to list1 in the same way that "*num2" is similar to num1?  Is num2 going to call a dereferencer, or try to turn a MyList into a MyList?

Really struggling with what's going on under the hood here.  Thanks!

答:
The overloaded operator* will only go in effect if you use it directly on an object of the class you defined it on. It has no effect on pointers to such objects. If you use * on a pointer, it will just dereference it to the underlying object. Additional * would invoke the overloaded operator*.

```<code>MyIterator *iter = new MyIterator();
*iter;  // This will only dereference the pointer.
**iter; // This will dereference the pointer and call your operator*.
</code>```

In your case the ptr->operator*() works, because the -> already does the first dereference. It is equivalent to (*ptr).operator*().

Note that iterators are usually used by-value, you will rarely find them behind a pointer.

Body:
I'm creating an iterator for a list class.  The iterator has a dereference operator:

    T& operator*() const {
        return this->currentNode->data;
    }

While trying to use the iterator:

for( ; list->begin() != list->end; (*list_iter).operator++())
{
    cout << list_iter << endl;
    cout << list_iter->operator*() << endl;
    //cout << *list_iter << endl;  //not working
}

The commented line says "invalid operand to binary experssion ostream and MyList::iterator".  Likewise, if I change from (*list_iter).operator++() to list_iter++ or (*list_iter)++, I get a similar error.

What I think is happening is something like this:

int num1 = 3;
int *num2 = new int;
*num2 = 3;

In this case, num1 is == *num2...  *num2 is functionally similar to num1 (both are integers), though num2 is a pointer to an integer, the *num2 makes it an integer.

So in:

MyList list1();
MyList *list2 = new MyList();

In this case, should I expect "*list2" to be similar to list1 in the same way that "*num2" is similar to num1?  Is num2 going to call a dereferencer, or try to turn a MyList into a MyList?

Really struggling with what's going on under the hood here.  Thanks!

Body:
The overloaded operator* will only go in effect if you use it directly on an object of the class you defined it on. It has no effect on pointers to such objects. If you use * on a pointer, it will just dereference it to the underlying object. Additional * would invoke the overloaded operator*.

MyIterator *iter = new MyIterator();
*iter;  // This will only dereference the pointer.
**iter; // This will dereference the pointer and call your operator*.

In your case the ptr->operator*() works, because the -> already does the first dereference. It is equivalent to (*ptr).operator*().

Note that iterators are usually used by-value, you will rarely find them behind a pointer.


问:
MSSQL select customers with same products
Hello I would like to SELECT the name of the customer who ordered this set of products like the Brazilian customers from Northwind database. I did brazilian products here:

```<code>select [ProductName]
from [dbo].[Products] join [dbo].[Order Details] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
join [dbo].[Orders] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Customers] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where [Country] = 'Brazil'
</code>```

but what now? How I can find them? I tried to do:

```<code>select [CompanyName], [ProductName]
from [dbo].[Customers] join [dbo].[Orders] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
join [dbo].[Order Details] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Products] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
where  [ProductName] in  (
select [ProductName]
from [dbo].[Products] join [dbo].[Order Details] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
join [dbo].[Orders] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Customers] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where [Country] = 'Brazil')
</code>```

but this also doesn't work :/

答:
You understand the schema wrong. Products from Brazil need check against suppliers

```<code>  SELECT ProductID
  FROM Products P
  JOIN Suppliers S
    ON P.SupplierID = S.SupplierID
  WHERE S.Country = 'Brazil'
</code>```

Then customer buying Brazil products are

```<code> SELECT DISTINCT C.CustomerID
 FROM Customer C
 JOIN Orders O
   ON C.CustomerID = O.CustomerID
 JOIN OrderDetails OD
   ON O.OrderID = OD.OrderID
 WHERE OD.ProductID IN ( SELECT ProductID
                         FROM Products P
                         JOIN Suppliers S
                           ON P.SupplierID = S.SupplierID
                         WHERE S.Country = 'Brazil')
</code>```

Body:
Hello I would like to SELECT the name of the customer who ordered this set of products like the Brazilian customers from Northwind database. I did brazilian products here:

select [ProductName]
from [dbo].[Products] join [dbo].[Order Details] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
join [dbo].[Orders] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Customers] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where [Country] = 'Brazil'

but what now? How I can find them? I tried to do:

select [CompanyName], [ProductName]
from [dbo].[Customers] join [dbo].[Orders] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
join [dbo].[Order Details] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Products] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
where  [ProductName] in  (
select [ProductName]
from [dbo].[Products] join [dbo].[Order Details] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
join [dbo].[Orders] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Customers] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where [Country] = 'Brazil')

but this also doesn't work :/

Body:
You understand the schema wrong. Products from Brazil need check against suppliers

  SELECT ProductID
  FROM Products P
  JOIN Suppliers S
    ON P.SupplierID = S.SupplierID
  WHERE S.Country = 'Brazil'

Then customer buying Brazil products are

 SELECT DISTINCT C.CustomerID
 FROM Customer C
 JOIN Orders O
   ON C.CustomerID = O.CustomerID
 JOIN OrderDetails OD
   ON O.OrderID = OD.OrderID
 WHERE OD.ProductID IN ( SELECT ProductID
                         FROM Products P
                         JOIN Suppliers S
                           ON P.SupplierID = S.SupplierID
                         WHERE S.Country = 'Brazil')