Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R/Rstudio Crashes after running filter #602

Closed
avwilliams opened this issue Sep 16, 2014 · 26 comments
Closed

R/Rstudio Crashes after running filter #602

avwilliams opened this issue Sep 16, 2014 · 26 comments
Assignees
Labels
feature a feature request or enhancement
Milestone

Comments

@avwilliams
Copy link

System:
Distributor ID: Ubuntu
Description: Ubuntu 12.04.5 LTS
Release: 12.04
Codename: precise

Kernel
3.8.0-32-lowlatency #24-Ubuntu SMP PREEMPT x86_64 GNU/Linux

Mem: 6112764

R version 3.1.1 (2014-07-10)
Platform: x86_64-pc-linux-gnu (64-bit)

RStudio
Version 0.98.932

library(dplyr)
library(rjson)
library(RJSONIO)
library(jsonlite)

Data Source:
socrata.afl <- fromJSON("https://data.cityofchicago.org/resource/alternative-fuel-locations.json?")
dim(socrata.afl)
## [1] 131  32
str(socrata.afl)
## 'data.frame':  131 obs. of  32 variables:
object_size(socrata.afl)
## 87.3 kB

Every time i run this command R/Rstusio Crashes

filter(socrata.afl, fuel_type_code %in% "LPG")
filter(socrata.afl, fuel_type_code == "LPG")
Error:
R Session Aborted
R encountered a fatal error.
The session was terminated
Start New Session

These work

subset(socrata.afl, fuel_type_code == "LPG")
subset(socrata.afl, fuel_type_code %in% "LPG")

Data Coerced Source:
socrata.afl.dt <- tbl_dt(socrata.afl)
This works:
filter(socrata.afl.dt, fuel_type_code == "LPG")

This does not, but R/Rstudio does not crash.
subset(socrata.afl.dt, fuel_type_code == "LPG")
Error in FUN(X[[2L]], ...) :
Invalid column: it has dimensions. Can't format it. If it's the result of data.table(table()), use as.data.table(table()) instead.

Any help kindly appreciated.

@romainfrancois
Copy link
Member

I get this:

> socrata.afl <- fromJSON("https://data.cityofchicago.org/resource/alternative-fuel-locations.json")
Error in file(con, "r") : cannot open the connection

@avwilliams
Copy link
Author

Try with the question mark at the end of the URL.

@hadley
Copy link
Member

hadley commented Sep 16, 2014

@avwilliams that's unlikely to work - fromJSON() uses R's connections which don't work with https. Loading three different packages for dealing with json is unlikely to help

@avwilliams
Copy link
Author

I did have that issue initially, but switching to http did not works as well.
I am not sure if puting the libraries in this order helped,

library(rjson)
library(RJSONIO)
library(jsonlite)

but this is what im getting now

Data

Alternative fule locations

socrata.afl <- fromJSON("https://data.cityofchicago.org/resource/alternative-fuel-locations.json?")
dim(socrata.afl)
# [1] 131  32
str(socrata.afl)
# 'data.frame':  131 obs. of  32 variables:
# object_size(socrata.afl)
# 87.3 kB

These work:

subset(socrata.afl, fuel_type_code %in% "LPG" )
socrata.afl.dt <- tbl_dt(socrata.afl)
dim(socrata.afl.dt)
# [1] 131  32
str(socrata.afl.dt)
# Classes ‘tbl_dt’, ‘tbl’, ‘data.table’ and 'data.frame':  131 obs. of  32 variables:
names(socrata.afl.dt)
filter(socrata.afl.dt, fuel_type_code == "LPG")

These crashes R/RStudio

filter(socrata.afl, fuel_type_code %in% "LPG")

Data Usage example 2

earthquakesDataFrame <- read.socrata("https://soda.demo.socrata.com/dataset/USGS-Earthquakes-for-2012-11-01-API-School-Demo/4334-bgaj")
nrow(earthquakesDataFrame) # 1007 (two "pages")
# [1] 1007
class(earthquakesDataFrame$Datetime[1]) # POSIXlt
# [1] "POSIXlt" "POSIXt" 

filter(earthquakesDataFrame, Region %in% "Southern California")

This gives this error

socrata.afl.dt.lpg <- filter(socrata.afl.dt, fuel_type_code %in% "LPG")
select(socrata.afl.dt.lpg, station_name, street_address, city, state, zip,
+ status_code, cards_accepted, street_address, access_days_time)
Error in select(socrata.afl.dt.lpg, station_name, street_address, city,  : 
  unused arguments (station_name, street_address, city, state, zip, status_code, cards_accepted, street_address, access_days_time)

@hadley
Copy link
Member

hadley commented Sep 16, 2014

Can you:

  1. Please use surround your R code with ````R` and `````
  2. Create a minimal example that demonstrates your problem using a built in dataset

@avwilliams
Copy link
Author

Sorry, just realised view is using markdown

@avwilliams
Copy link
Author

Functions woking fine with built-in dataset

library(MASS)

min age

min.age <- Pima.tr2 %>%
  filter(age == 21) %>%
  select(age, bp, bmi, glu)
head(min.age)
  age bp  bmi glu
1  21 76 23.2  99
2  21 60 25.4 109
3  21 62 22.1 139
4  21 64 21.0 101
5  21 58 25.4  99
6  21 64 18.2  97

max age

max.age <- Pima.tr2 %>%
  filter(age == 72) %>%
  select(age, bp, bmi, glu)

head(max.age)
  age bp  bmi glu
1  72 NA 19.6 119

###med - mean ages

mm.age <- Pima.tr2 %>%
  filter(age == 29:33) %>%
  select(age, bp, bmi, glu)

head(mm.age)
  age bp  bmi glu
1  31 60 27.5 129
2  30 74 27.8 124
3  29 84 39.4 158
4  31 76 23.8 114
5  30 62 29.7 117
6  31 66 39.1 103

@romainfrancois
Copy link
Member

I can reproduce this now, with a bit of editing of the code. This consistently crashes my session indeed:

library(methods)
library(devtools)
library(magrittr)

load_all()
library(rjson)
library(RJSONIO)
library(jsonlite)

socrata.afl <- fromJSON("https://data.cityofchicago.org/resource/alternative-fuel-locations.json")
dim(socrata.afl)

filter(socrata.afl, fuel_type_code %in% "LPG")

However, I only get the segfault on printing the data, so if I do:

res <- filter(socrata.afl, fuel_type_code %in% "LPG")

it's fine, but then it breaks when I run:

res

And that's what lldb has to say about it:

> res
Process 7160 stopped
* thread #1: tid = 0x9e1a9, 0x00000001000889d7 libR.dylib`duplicate1(s=0x646f6365725f7364, deep=TRUE) + 23 at duplicate.c:274, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    frame #0: 0x00000001000889d7 libR.dylib`duplicate1(s=0x646f6365725f7364, deep=TRUE) + 23 at duplicate.c:274
(lldb) bt
* thread #1: tid = 0x9e1a9, 0x00000001000889d7 libR.dylib`duplicate1(s=0x646f6365725f7364, deep=TRUE) + 23 at duplicate.c:274, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
  * frame #0: 0x00000001000889d7 libR.dylib`duplicate1(s=0x646f6365725f7364, deep=TRUE) + 23 at duplicate.c:274
    frame #1: 0x0000000100088dcd libR.dylib`duplicate1 [inlined] duplicate_child(s=0x646f6365725f7364, deep=TRUE) + 66 at duplicate.c:199
    frame #2: 0x0000000100088d8b libR.dylib`duplicate1(s=0x0000000106292e38, deep=TRUE) + 971 at duplicate.c:329
    frame #3: 0x0000000100088dcd libR.dylib`duplicate1 [inlined] duplicate_child(s=0x0000000106292e38, deep=TRUE) + 66 at duplicate.c:199
    frame #4: 0x0000000100088d8b libR.dylib`duplicate1(s=0x0000000108a00450, deep=TRUE) + 971 at duplicate.c:329
    frame #5: 0x000000010008a7dd libR.dylib`duplicate_list [inlined] duplicate_child(s=0x0000000108a00450, deep=TRUE) + 67 at duplicate.c:199
    frame #6: 0x000000010008a79a libR.dylib`duplicate_list(s=<unavailable>, deep=TRUE) + 202 at duplicate.c:261
    frame #7: 0x0000000100088f13 libR.dylib`duplicate1(s=0x0000000107c1e190, deep=TRUE) + 1363 at duplicate.c:308
    frame #8: 0x000000010008897b libR.dylib`Rf_duplicate(s=0x0000000107c1e190) + 27 at duplicate.c:132
    frame #9: 0x00000001000ed0a9 libR.dylib`Rf_usemethod(generic=0x00000001008a10f0, obj=0x0000000108a00450, call=<unavailable>, args=<unavailable>, rho=0x0000000107c1ed48, callrho=0x0000000100850d40, defrho=<unavailable>, ans=<unavailable>) + 537 at objects.c:308
    frame #10: 0x00000001000edf86 libR.dylib`do_usemethod(call=0x0000000107c1eed0, op=<unavailable>, args=<unavailable>, env=0x0000000107c1ed48) + 790 at objects.c:449
    frame #11: 0x00000001000a7ce5 libR.dylib`bcEval(body=<unavailable>, rho=0x0000000107c1ed48, useCache=<unavailable>) + 10869 at eval.c:4775
    frame #12: 0x00000001000a4bc6 libR.dylib`Rf_eval(e=0x0000000107c1ef08, rho=0x0000000107c1ed48) + 358 at eval.c:560
    frame #13: 0x00000001000b0690 libR.dylib`Rf_applyClosure(call=<unavailable>, op=<unavailable>, arglist=<unavailable>, rho=<unavailable>, suppliedenv=<unavailable>) + 1600 at eval.c:1038
    frame #14: 0x00000001000a4ffd libR.dylib`Rf_eval(e=0x0000000107c1e190, rho=0x0000000100850d40) + 1437 at eval.c:676
    frame #15: 0x0000000100110648 libR.dylib`Rf_PrintValueEnv(s=<unavailable>, env=0x0000000100850d40) + 552 at print.c:993
    frame #16: 0x00000001000df156 libR.dylib`Rf_ReplIteration(rho=<unavailable>, savestack=<unavailable>, browselevel=<unavailable>, state=0x00007fff5fbfe8e0) + 1142 at main.c:264
    frame #17: 0x00000001000e03c3 libR.dylib`run_Rmainloop [inlined] R_ReplConsole(rho=0x0000000100850d40, savestack=<unavailable>, browselevel=<unavailable>) + 97 at main.c:310
    frame #18: 0x00000001000e0362 libR.dylib`run_Rmainloop + 98 at main.c:1002
    frame #19: 0x0000000100000f3b R`main + 27
    frame #20: 0x00007fff90c1b5fd libdyld.dylib`start + 1

@romainfrancois
Copy link
Member

It also happens if I print socrata.afl after making res.

@romainfrancois
Copy link
Member

One of the problem I guess is that some of the columns of socrata.afl are themselves data frames and I'm pretty sure we're not going to handle that properly, i.e. this works:

socrata.afl <- socrata.afl[ , sapply(socrata.afl, class) != "data.frame" ]
res <- filter(socrata.afl, fuel_type_code %in% "LPG")
res

R's subset applies the filter on the inner data frames, i.e. :

> subset(socrata.afl, fuel_type_code == "LPG")$location
    needs_recoding   longitude   latitude
40           FALSE -87.7472764 41.9587882
65           FALSE   -87.74629  41.911962
105          FALSE -87.5840203 41.7662273
124          FALSE -87.6511547 41.8872821

@hadley do we want this or should we just forbid weird data structures like this, it does not look tidy to me.

@hadley
Copy link
Member

hadley commented Sep 22, 2014

Here's a minimal example:

afl <- jsonlite::fromJSON("https://data.cityofchicago.org/resource/alternative-fuel-locations.json")
res <- dplyr::filter(afl, fuel_type_code %in% "LPG")

I'd say this is technically a bug in dplyr, since [ does recursively subset data frames and matrices. How hard would it be to add an additional switch when one of the columns is a data frame or matrix? (A data frame as a column is not useful, but a matrix sometimes is.) I think you already have something similar for lists?

This is relatively low priority since it's a pretty esoteric feature of data frame subsetting, but it would be nice if it worked.

@hadley hadley added the feature a feature request or enhancement label Sep 22, 2014
@hadley hadley added this to the 0.3.1 milestone Sep 22, 2014
@romainfrancois
Copy link
Member

and the matrix would have to have the same number of rows as the host data frame ? and have colnames ?

I think this would mean updating some code in the LazySubsets et al. classes. Should be fairly straight forward for inner data frames as I can just pick up vectors from it.

For matrices, I could either be lazy and copy columns into a brand new vector, or come up with some sort of virtual vector.

Does not sound that horrible to implement. I'll marinate this a bit.

@hadley
Copy link
Member

hadley commented Sep 22, 2014

Yes, the internal matrix/data frame should have nrow() equal to nrow(df). It doesn't need column names.

@romainfrancois
Copy link
Member

I've put some code in to support data frames as columns of data frames. So the reprex gives:

> load_all()
Loading dplyr
>
> afl <- jsonlite::fromJSON("https://data.cityofchicago.org/resource/alternative-fuel-locations.json")
> res <- dplyr::filter(afl, fuel_type_code %in% "LPG")
> res
  needs_recoding   longitude   latitude open_date state geocode_status    city
1          FALSE -87.7472764 41.9587882      <NA>    IL          200-8 Chicago
2          FALSE   -87.74629  41.911962      <NA>    IL          200-8 Chicago
3          FALSE -87.5840203 41.7662273      <NA>    IL          200-8 Chicago
4          FALSE -87.6511547 41.8872821      <NA>    IL          200-8 Chicago
  fuel_type_code    id   longitude status_code   zip station_name
1            LPG 19925 -87.7472764         200 60641       U-Haul
2            LPG 19924   -87.74629         200 60639       U-Haul
3            LPG 19926 -87.5840203         200 60649       U-Haul
4            LPG 15014 -87.6511547         200 60607     AmeriGas
  owner_type_code groups_with_access_code station_phone date_last_confirmed
1               P                  Public  773-286-4507 2014-11-04T00:00:00
2               P                  Public  773-889-8194 2014-11-04T00:00:00
3               P     Public - Call ahead  773-493-1206 2014-11-04T00:00:00
4               P                  Public  312-997-2300 2014-11-04T00:00:00
  updated_at ev_level2_evse_num   latitude    street_address
1 1415144131               <NA> 41.9587882 4301 N Cicero Ave
2 1415143736               <NA>  41.911962 1700 N Cicero Ave
3 1415143488               <NA> 41.7662273    1650 E 71st St
4 1415143516               <NA> 41.8872821 310 N Sangamon St
                              access_days_time
1 7am-7pm M-Th and Sat, 7am-8pm F, 8am-6pm Sun
2 7am-7pm M-Th and Sat, 7am-8pm F, 9am-5pm Sun
3 7am-7pm M-Th and Sat, 7am-8pm F, 9am-5pm Sun
4                                  6am-4pm M-F
                                    intersection_directions  url ev_network
1                                                      <NA> <NA>       <NA>
2                                   Between North and Grand <NA>       <NA>
3                                          At Stoney Island <NA>       <NA>
4 4 blocks west of Interstate 90/94, 2 blocks north of Lake <NA>       <NA>
  ev_level1_evse_num ng_psi ng_fill_type_code ng_vehicle_class cards_accepted
1               <NA>   <NA>              <NA>             <NA>   A Cash D M V
2               <NA>   <NA>              <NA>             <NA>   A Cash D M V
3               <NA>   <NA>              <NA>             <NA>   A Cash D M V
4               <NA>   <NA>              <NA>             <NA>   A Cash D M V
  e85_blender_pump ev_dc_fast_count lpg_primary
1             <NA>             <NA>        true
2             <NA>             <NA>        true
3             <NA>             <NA>       false
4             <NA>             <NA>       false

Matrices next, when I understand what to do with them

@romainfrancois
Copy link
Member

So some explanation of how I treated inner data frames (support might still be a bit rough). Essentially what I do is treat columns of the inner df as if it were a column of the host data frame.

> df <- data.frame( a = 1:10, b = 1:10, c = 1:10 )
> df$b <- data.frame( x = 1:10, y = 1:10 )
> str(df)
'data.frame':   10 obs. of  3 variables:
 $ a: int  1 2 3 4 5 6 7 8 9 10
 $ b:'data.frame':  10 obs. of  2 variables:
  ..$ x: int  1 2 3 4 5 6 7 8 9 10
  ..$ y: int  1 2 3 4 5 6 7 8 9 10
 $ c: int  1 2 3 4 5 6 7 8 9 10
> filter( df, x < 5 )
  a x y c
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4

So I just pretend that x and y are legit columns of df. Is that alright, or should I somehow retain the weird format, e.g. produce a data frame with an inner data frame again, i.e. what base::subset does:

> subset( df, a < 5 ) %>% str
'data.frame':   4 obs. of  3 variables:
 $ a: int  1 2 3 4
 $ b:'data.frame':  4 obs. of  2 variables:
  ..$ x: int  1 2 3 4
  ..$ y: int  1 2 3 4
 $ c: int  1 2 3 4

Another question, I've used the inner names as the names of the output df. Is that alright or should I somehow produce names based on the name of the host column and the column names of the inner df, e.g. b.x and b.y

I think this is a pretty esoteric case anyway, so I'm happy with what I have done. Will add tests for various verbs and with groups, etc ...

Part of me feels that this warrants an update of Rcpp::DataFrame or perhaps bring back the idea of this data frame c++ library we once mentioned.

@romainfrancois
Copy link
Member

About matrices:

> df <- data.frame( a = 1:10, b = 1:10, c = 1:10 )
> df$b <- matrix( 1:20, ncol = 2 )
> str(df)
'data.frame':   10 obs. of  3 variables:
 $ a: int  1 2 3 4 5 6 7 8 9 10
 $ b: int [1:10, 1:2] 1 2 3 4 5 6 7 8 9 10 ...
 $ c: int  1 2 3 4 5 6 7 8 9 10
> df
    a b.1 b.2  c
1   1   1  11  1
2   2   2  12  2
3   3   3  13  3
4   4   4  14  4
5   5   5  15  5
6   6   6  16  6
7   7   7  17  7
8   8   8  18  8
9   9   9  19  9
10 10  10  20 10

Based on what subset does:

> subset( df, a < 5 )
  a b.1 b.2 c
1 1   1  11 1
2 2   2  12 2
3 3   3  13 3
4 4   4  14 4
>
> subset( df, a < 5 ) %>% str
'data.frame':   4 obs. of  3 variables:
 $ a: int  1 2 3 4
 $ b: int [1:4, 1:2] 1 2 3 4 11 12 13 14
 $ c: int  1 2 3 4

I can see two ways of doing this:

  • copy each column into a vector, making up the name as {name of host column} + position and then just proceed normally. This is I think easy to implement.
  • extend visitors so that we have matrix visitors. This might be more difficult to implement, but this will give us something perhaps closer to what subset does, i.e. produce a matrix as output too.

Thinking about this, perhaps option 2 could be also used for inner data frames instead of what I did so far.

Anyway, over to you @hadley; Tell me what you think of all this.

@hadley
Copy link
Member

hadley commented Nov 6, 2014

It's not clear to me what filter( df, x < 5 ) should do. I think we have two options:

  • filter( df, x < 5 ) returns an error
  • Let filter( df, b$x < 5 ) work.

I think the main thing with filtering when one column is a data frame, is correctly subsetting that data frame when you're filtering on a regular column. i.e. what's important to me is that filter(df, a < 3) should work, preserving the existing structure.

@romainfrancois
Copy link
Member

Alright, that's not what I've put in. To make filter(df, a < 3) work and retain a data frame under the column b I need to come up with some sort of visitor for data frames.

Making filter( df, x < 5 ) fail should be straightforward.

I'm just a tiny bit more concerned about making filter( df, b$x < 5 ) work.

That answers the question about handling of matrices too, I'll try to keep the structure intact.

@hadley
Copy link
Member

hadley commented Nov 6, 2014

I'd say:

  • For 0.3.1, all we need is an error message here, instead of a crash
  • For 0.4, we should preserve data.frame/matrices when filtering on other variables
  • At some point in the future, >= 0.5, filter( df, b$x < 5 ) should work

romainfrancois added a commit that referenced this issue Nov 7, 2014
@romainfrancois
Copy link
Member

Ok I've now put various protections in place to forbid data frames and matrices columns.

> filter( df, a < 5 )
Erreur : column 'b' has unsupported type : matrix

So I'm promoting this to 0.4 now.

Or perhaps we should create a new issue. We also need to have a look at how this affects other verbs, e.g. how do we arrange based on a matrix column ? lexicographic ordering ? ...

The bulk of work for this is on the 0.4 item, once we have this in place, it should be relatively easy to allow b$x < 5 to work .

@romainfrancois romainfrancois modified the milestones: 0.4, 0.3.1 Nov 7, 2014
romainfrancois added a commit that referenced this issue Nov 11, 2014
…rVisitor`

  concept for a column that is a `data.frame`. Part of #602.
@romainfrancois
Copy link
Member

Can now preserve data.framestructure when filtering on other columns.

> df <- data.frame( a = 1:10, b = 1:10, c = 1:10 )
> df$b <- data.frame( x = 1:10, y = 1:10 )
> df %>% filter( a < 5 ) %>% str
'data.frame':   4 obs. of  3 variables:
 $ a: int  1 2 3 4
 $ b:'data.frame':  4 obs. of  2 variables:
  ..$ x: int  1 2 3 4
  ..$ y: int  1 2 3 4
 $ c: int  1 2 3 4

romainfrancois added a commit that referenced this issue Nov 11, 2014
  `VectorVisitor` concept for a column that is a `matrix`. Part of #602
@romainfrancois
Copy link
Member

And now also matrices:

> df <- data.frame( a = 1:10, b = 1:10, c = 1:10 )
> df$b <- matrix( 1:20, nrow = 10 )
> res <- filter( df, a < 5 )
> res %>% str
'data.frame':   4 obs. of  3 variables:
 $ a: int  1 2 3 4
 $ b: int [1:4, 1:2] 1 2 3 4 11 12 13 14
 $ c: int  1 2 3 4

@romainfrancois
Copy link
Member

Next I guess is dealing with other kinds of visitors, i.e. OrderVisitor for arrange and order and JoinVisitor for *_join.

@romainfrancois
Copy link
Member

I'm now getting:

df <- data.frame( a = 1:10, b = 1:10, c = 1:10 )
df$b <- data.frame( x = 1:10, y = 1:10 )
df %>% filter( a < 5 ) %>% str
# Erreur : data_frames can only contain 1d atomic vectors and lists

because:

> filter_.data.frame
function(.data, ..., .dots) {
  dots <- lazyeval::all_dots(.dots, ..., all_named = TRUE)
  as.data.frame(filter_(tbl_df(.data), .dots = dots))
}

> tdf <- tbl_df(df)
Erreur : data_frames can only contain 1d atomic vectors and lists

ping @hadley.

@romainfrancois
Copy link
Member

I've put some simple change in the more_data_frame branch so that as_data_frame does less if the object is already a data.frame.

So I can get to :

> df <- data.frame( a = 1:10, b = 1:10, c = 1:10 )
> df$b <- data.frame( x = 1:10, y = 1:10 )
> res <- df %>% filter( a < 5 )
> str(res)
'data.frame':   4 obs. of  3 variables:
 $ a: int  1 2 3 4
 $ b:'data.frame':  4 obs. of  2 variables:
  ..$ x: int  1 2 3 4
  ..$ y: int  1 2 3 4
 $ c: int  1 2 3 4

So the internal code does the right thing.

However, we can't print those objects:

> tbl_df(df)
Source: local data frame [10 x 3]

Error in `[.data.frame`(X[[i]], ...) : undefined columns selected
> tbl_df(res)
Source: local data frame [4 x 3]

Error in `[.data.frame`(X[[i]], ...) : undefined columns selected

Apparently this happens in trunc_mat formatting code. I'm not so familiar with that part of the code. So I'm reassigning this to @hadley

@hadley
Copy link
Member

hadley commented Oct 22, 2015

I think this is now correct - I get "data_frames can only contain 1d atomic vectors and lists " - the first column of this data frame is another data frame, which dplyr does not support.

@hadley hadley closed this as completed Oct 22, 2015
@lock lock bot locked as resolved and limited conversation to collaborators Jun 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature a feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants