Repository: modin-project/modin

Issue:
`DataFrame.sub` and other binary operators always have a null `fill_value`
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: All
- **Modin version** (`modin.__version__`): 0.7.1
- **Python version**: All
- **Code we can use to reproduce**:

```python
df.sub(df2, fill_value=0)
```

### Describe the problem
<!-- Describe the problem clearly here. -->
We are automatically converting all fill values for `DataFrame.sub` to `None`.

### Source code / logs

https://github.com/modin-project/modin/blob/master/modin/pandas/dataframe.py#L1583

cc @magnatelee
<!-- Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached. Try to provide a reproducible test case that is the bare minimum necessary to generate the problem. -->



Discussion:

Resolving patch:
diff --git a/modin/pandas/dataframe.py b/modin/pandas/dataframe.py
--- a/modin/pandas/dataframe.py
+++ b/modin/pandas/dataframe.py
@@ -684,7 +684,7 @@ def floordiv(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).floordiv(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     @classmethod
@@ -1186,14 +1186,14 @@ def mod(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).mod(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     def mul(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).mul(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     rmul = multiply = mul
@@ -1280,7 +1280,7 @@ def pow(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).pow(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     def prod(
@@ -1414,35 +1414,35 @@ def rfloordiv(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).rfloordiv(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     def rmod(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).rmod(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     def rpow(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).rpow(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     def rsub(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).rsub(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     def rtruediv(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).rtruediv(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     rdiv = rtruediv
@@ -1580,7 +1580,7 @@ def sub(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).sub(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     subtract = sub
@@ -1768,7 +1768,7 @@ def truediv(self, other, axis="columns", level=None, fill_value=None):
         if isinstance(other, Series):
             other = other._to_pandas()
         return super(DataFrame, self).truediv(
-            other, axis=axis, level=level, fill_value=None
+            other, axis=axis, level=level, fill_value=fill_value
         )
 
     div = divide = truediv


Test patch:
diff --git a/modin/pandas/test/test_dataframe.py b/modin/pandas/test/test_dataframe.py
--- a/modin/pandas/test/test_dataframe.py
+++ b/modin/pandas/test/test_dataframe.py
@@ -112,6 +112,16 @@ def inter_df_math_helper(self, modin_df, pandas_df, op):
             modin_result = getattr(modin_df, op)(modin_df2)
             df_equals(modin_result, pandas_result)
 
+        # Test dataframe fill value
+        try:
+            pandas_result = getattr(pandas_df, op)(pandas_df2, fill_value=0)
+        except Exception as e:
+            with pytest.raises(type(e)):
+                getattr(modin_df, op)(modin_df2, fill_value=0)
+        else:
+            modin_result = getattr(modin_df, op)(modin_df2, fill_value=0)
+            df_equals(modin_result, pandas_result)
+
         # Test dataframe to list
         list_test = random_state.randint(RAND_LOW, RAND_HIGH, size=(modin_df.shape[1]))
         try: