ronantakizawa/codereview-bench huggingface dataset:
Repository: casey/just
File: src/analyzer.rs (Rust)

Code before:
    }

    Ok(())
  }

  fn resolve_alias<'a>(
    modules: &'a Table<'src, Justfile<'src>>,
    recipes: &'a Table<'src, Rc<Recipe<'src>>>,
    alias: Alias<'src, Namepath<'src>>,
  ) -> CompileResult<'src, Alias<'src>> {
    // Make sure the target recipe exists
    match Self::recipe_from_path(alias.target.as_ref(), modules, recipes) {
      Some(target) => Ok(alias.resolve(target)),
      None => Err(alias.name.token.error(UnknownAliasTarget {
        alias: alias.name.lexeme(),
        target: alias.target,
      })),
    }
  }

  fn recipe_from_path<'a>(
    path: &[Name],
    mut modules: &'a Table<'src, Justfile<'src>>,
    mut recipes: &'a Table<'src, Rc<Recipe<'src>>>,
  ) -> Option<Rc<Recipe<'src>>> {
    let name = path.last()?;
    let module_path = &path[0..path.len() - 1];

    for module_name in module_path {
      let just_file = modules.get(module_name.lexeme())?;
      recipes = &just_file.recipes;
      modules = &just_file.modules;
    }

    recipes.get(name.lexeme()).cloned()
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  analysis_error! {
    name: duplicate_alias,
    input: "alias foo := bar\nalias foo := baz",
    offset: 23,
    line: 1,
    column: 6,
    width: 3,
    kind: Redefinition { first_type: "alias", second_type: "alias", name: "foo", first: 0 },
  }

Review comment (bug):
What happens if `.last()` return `None`? This will be treated as an unknown alias target, but is in fact a bug, since namepath should be non-empty, and thus if `.last()` returns `None` it should be an internal error. This is why we shouldn't iplement `Deref` for `Namepath`, because the function signature `fn last(&self) -> Option<Name>` doesn't make sense. It should be `fn last(&self) -> Name`.

Code after:
    }

    Ok(())
  }

  fn resolve_alias<'a>(
    modules: &'a Table<'src, Justfile<'src>>,
    recipes: &'a Table<'src, Rc<Recipe<'src>>>,
    alias: Alias<'src, Namepath<'src>>,
  ) -> CompileResult<'src, Alias<'src>> {
    match Self::alias_target(&alias.target, modules, recipes) {
      Some(target) => Ok(alias.resolve(target)),
      None => Err(alias.name.token.error(UnknownAliasTarget {
        alias: alias.name.lexeme(),
        target: alias.target,
      })),
    }
  }

  fn alias_target<'a>(
    path: &Namepath<'src>,
    mut modules: &'a Table<'src, Justfile<'src>>,
    mut recipes: &'a Table<'src, Rc<Recipe<'src>>>,
  ) -> Option<Rc<Recipe<'src>>> {
    let (name, path) = path.split_last();

    for name in path {
      let module = modules.get(name.lexeme())?;
      modules = &module.modules;
      recipes = &module.recipes;
    }

    recipes.get(name.lexeme()).cloned()
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  analysis_error! {
    name: duplicate_alias,
    input: "alias foo := bar\nalias foo := baz",
    offset: 23,
    line: 1,
    column: 6,
    width: 3,
    kind: Redefinition { first_type: "alias", second_type: "alias", name: "foo", first: 0 },
  }

  analysis_error! {
Repository: casey/just
File: src/namepath.rs (Rust)

Code before:
use super::*;

#[derive(Clone, Debug, Eq, Ord, PartialOrd)]
pub(crate) struct Namepath<'src>(Vec<Name<'src>>);

impl PartialEq for Namepath<'_> {
  fn eq(&self, other: &Self) -> bool {
    let self_lexeme_iter = self.lexeme_iter();
    let other_lexeme_iter = other.lexeme_iter();
    if self_lexeme_iter.len() != other_lexeme_iter.len() {
      return false;
    }
    self_lexeme_iter
      .zip(other_lexeme_iter)
      .all(|(self_lexeme, other_lexeme)| self_lexeme == other_lexeme)
  }
}

impl<'src> Namepath<'src> {
  pub(crate) fn join(&self, name: Name<'src>) -> Self {
    Self(self.0.iter().copied().chain(iter::once(name)).collect())
  }

  pub(crate) fn spaced(&self) -> ModulePath {
    ModulePath {
      path: self.0.iter().map(|name| name.lexeme().into()).collect(),
      spaced: true,
    }
  }

  pub fn push(&mut self, name: Name<'src>) {

Review comment (suggestion):
I don't think we should implement a `PartialEq` implementation which ignores everything but the lexeme.

I think we should do `fn is_same_path(&self, other: &Self) -> bool` which compares the lexemes.

Code after:
use super::*;

#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
pub(crate) struct Namepath<'src>(Vec<Name<'src>>);

impl<'src> Namepath<'src> {
  pub(crate) fn join(&self, name: Name<'src>) -> Self {
    Self(self.0.iter().copied().chain(iter::once(name)).collect())
  }

  pub(crate) fn spaced(&self) -> ModulePath {
    ModulePath {
      path: self.0.iter().map(|name| name.lexeme().into()).collect(),
      spaced: true,
    }
  }

  pub(crate) fn push(&mut self, name: Name<'src>) {
    self.0.push(name);
  }

  pub(crate) fn last(&self) -> &Name<'src> {
    self.0.last().unwrap()
  }

  pub(crate) fn split_last(&self) -> (&Name<'src>, &[Name<'src>]) {
    self.0.split_last().unwrap()
  }

  #[cfg(test)]
  pub(crate) fn iter(&self) -> slice::Iter<'_, Name<'src>> {
Repository: casey/just
File: src/namepath.rs (Rust)

Code before:
    if self_lexeme_iter.len() != other_lexeme_iter.len() {
      return false;
    }
    self_lexeme_iter
      .zip(other_lexeme_iter)
      .all(|(self_lexeme, other_lexeme)| self_lexeme == other_lexeme)
  }
}

impl<'src> Namepath<'src> {
  pub(crate) fn join(&self, name: Name<'src>) -> Self {
    Self(self.0.iter().copied().chain(iter::once(name)).collect())
  }

  pub(crate) fn spaced(&self) -> ModulePath {
    ModulePath {
      path: self.0.iter().map(|name| name.lexeme().into()).collect(),
      spaced: true,
    }
  }

  pub fn push(&mut self, name: Name<'src>) {
    self.0.push(name);
  }

  fn lexeme_iter(&self) -> impl ExactSizeIterator<Item = &str> {
    self.0.iter().map(|name| name.lexeme())
  }
}

impl Display for Namepath<'_> {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    for (i, name) in self.0.iter().enumerate() {
      if i > 0 {
        write!(f, "::")?;
      }
      write!(f, "{name}")?;
    }
    Ok(())
  }
}

impl<'src> From<Name<'src>> for Namepath<'src> {
  fn from(name: Name<'src>) -> Self {
    Self(vec![name])
  }
}

impl Serialize for Namepath<'_> {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  where

Review comment (refactor):
I don't think a helper function which is only used in one place adds much. `.all(|(a, b)| a.lexeme() == b.lexeme())` is fine.

Code after:

  pub(crate) fn spaced(&self) -> ModulePath {
    ModulePath {
      path: self.0.iter().map(|name| name.lexeme().into()).collect(),
      spaced: true,
    }
  }

  pub(crate) fn push(&mut self, name: Name<'src>) {
    self.0.push(name);
  }

  pub(crate) fn last(&self) -> &Name<'src> {
    self.0.last().unwrap()
  }

  pub(crate) fn split_last(&self) -> (&Name<'src>, &[Name<'src>]) {
    self.0.split_last().unwrap()
  }

  #[cfg(test)]
  pub(crate) fn iter(&self) -> slice::Iter<'_, Name<'src>> {
    self.0.iter()
  }

  #[cfg(test)]
  pub(crate) fn len(&self) -> usize {
    self.0.len()
  }
}

impl Display for Namepath<'_> {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    for (i, name) in self.0.iter().enumerate() {
      if i > 0 {
        write!(f, "::")?;
      }
      write!(f, "{name}")?;
    }
    Ok(())
  }
}

impl<'src> From<Name<'src>> for Namepath<'src> {
  fn from(name: Name<'src>) -> Self {
    Self(vec![name])
  }
}

impl Serialize for Namepath<'_> {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
Repository: casey/just
File: src/namepath.rs (Rust)

Code before:
    self.0.push(name);
  }

  pub fn iter(&self) -> std::slice::Iter<'_, Name<'src>> {
    self.0.iter()
  }

  pub fn len(&self) -> usize {
    self.0.len()
  }

  /// Returns the last name in the module path
  /// a::b::c -> c
  /// a       -> a
  pub fn last(&self) -> &Name<'src> {
    self
      .0
      .last()
      .expect("Internal error: Namepath can not be empty")
  }

  /// Splits a module path into the last name and its parent
  /// a::b::c -> (a::b, c)
  /// a       -> (empty, a)
  pub fn split_last(&self) -> (&[Name<'src>], &Name<'src>) {
    let name = self.last();

    (&self.0[..self.0.len() - 1], name)
  }
}

impl Display for Namepath<'_> {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    for (i, name) in self.0.iter().enumerate() {
      if i > 0 {
        write!(f, "::")?;
      }
      write!(f, "{name}")?;
    }
    Ok(())
  }
}

impl<'src> From<Name<'src>> for Namepath<'src> {
  fn from(name: Name<'src>) -> Self {
    Self(vec![name])
  }
}

impl Serialize for Namepath<'_> {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>

Review comment (bug):
Assigning this variable first instead of making this a one liner because `last()` will give a more meaningful panic message than `&self.0[..self.0.len() - 1]` panicking due to wrong indexing if `len()==0`

Code after:
    self.0.iter()
  }

  #[cfg(test)]
  pub(crate) fn len(&self) -> usize {
    self.0.len()
  }
}

impl Display for Namepath<'_> {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    for (i, name) in self.0.iter().enumerate() {
      if i > 0 {
        write!(f, "::")?;
      }
      write!(f, "{name}")?;
    }
    Ok(())
  }
}

impl<'src> From<Name<'src>> for Namepath<'src> {
  fn from(name: Name<'src>) -> Self {
    Self(vec![name])
  }
}

impl Serialize for Namepath<'_> {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  where
    S: Serializer,
  {
    serializer.serialize_str(&format!("{self}"))
  }
}
Repository: casey/just
File: src/compile_error_kind.rs (Rust)

Code before:
  UnicodeEscapeLength {
    hex: String,
  },
  UnicodeEscapeRange {
    hex: String,
  },
  UnicodeEscapeUnterminated,
  UnknownAliasTarget {
    alias: &'src str,
    target: &'src str,
  },
  UnknownAttribute {
    attribute: &'src str,
  },
  UnknownDependency {
    recipe: &'src str,
    unknown: &'src str,
  },
  UnknownFunction {
    function: &'src str,
  },
  UnknownSetting {
    setting: &'src str,
  },
  UnknownStartOfToken {
    token: char,
  },
  UnpairedCarriageReturn,
  UnterminatedBacktick,
  UnterminatedInterpolation,
  UnterminatedString,
}


Review comment (suggestion):
Perhaps call this `start`? Since it's not really a whole token. Also, `start` is the name of the variable in `lexer.rs`, so you can use shorthand initializer syntax there.

Code after:
  UnicodeEscapeLength {
    hex: String,
  },
  UnicodeEscapeRange {
    hex: String,
  },
  UnicodeEscapeUnterminated,
  UnknownAliasTarget {
    alias: &'src str,
    target: &'src str,
  },
  UnknownAttribute {
    attribute: &'src str,
  },
  UnknownDependency {
    recipe: &'src str,
    unknown: &'src str,
  },
  UnknownFunction {
    function: &'src str,
  },
  UnknownSetting {
    setting: &'src str,
  },
  UnknownStartOfToken {
    start: char,
  },
  UnpairedCarriageReturn,
  UnterminatedBacktick,
  UnterminatedInterpolation,
  UnterminatedString,
}
Repository: casey/just
File: src/compile_error.rs (Rust)

Code before:
        f,
        "unicode escape sequence starting with `\\u{{{hex}` longer than six hex digits"
      ),
      UnicodeEscapeRange { hex } => {
        write!(
          f,
          "unicode escape sequence value `{hex}` greater than maximum valid code point `10FFFF`",
        )
      }
      UnicodeEscapeUnterminated => write!(f, "unterminated unicode escape sequence"),
      UnknownAliasTarget { alias, target } => {
        write!(f, "Alias `{alias}` has an unknown target `{target}`")
      }
      UnknownAttribute { attribute } => write!(f, "Unknown attribute `{attribute}`"),
      UnknownDependency { recipe, unknown } => {
        write!(f, "Recipe `{recipe}` has unknown dependency `{unknown}`")
      }
      UnknownFunction { function } => write!(f, "Call to unknown function `{function}`"),
      UnknownSetting { setting } => write!(f, "Unknown setting `{setting}`"),
      UnknownStartOfToken { token } => write!(
        f,
        "Unknown start of token {}:",
        if token.is_ascii() {
          format!("'{token}'")
        } else {
          format!("'{token}' ({})", token.escape_unicode())
        }
      ),
      UnpairedCarriageReturn => write!(f, "Unpaired carriage return"),
      UnterminatedBacktick => write!(f, "Unterminated backtick"),
      UnterminatedInterpolation => write!(f, "Unterminated interpolation"),
      UnterminatedString => write!(f, "Unterminated string"),
    }
  }
}


Review comment (security):
I think the `escape_unicode` format isn't super useful. Let's use the `U+NNNN` representation, which is commonly used to represent unicode codepoints. `NNNN` should be four hex digits. Leading zeros should not be elided.

Code after:
        f,
        "unicode escape sequence starting with `\\u{{{hex}` longer than six hex digits"
      ),
      UnicodeEscapeRange { hex } => {
        write!(
          f,
          "unicode escape sequence value `{hex}` greater than maximum valid code point `10FFFF`",
        )
      }
      UnicodeEscapeUnterminated => write!(f, "unterminated unicode escape sequence"),
      UnknownAliasTarget { alias, target } => {
        write!(f, "Alias `{alias}` has an unknown target `{target}`")
      }
      UnknownAttribute { attribute } => write!(f, "Unknown attribute `{attribute}`"),
      UnknownDependency { recipe, unknown } => {
        write!(f, "Recipe `{recipe}` has unknown dependency `{unknown}`")
      }
      UnknownFunction { function } => write!(f, "Call to unknown function `{function}`"),
      UnknownSetting { setting } => write!(f, "Unknown setting `{setting}`"),
      UnknownStartOfToken { start } => {
        write!(f, "Unknown start of token '{start}'")?;
        if !start.is_ascii_graphic() {
          write!(f, " (U+{:04X})", *start as u32)?;
        }
        Ok(())
      }
      UnpairedCarriageReturn => write!(f, "Unpaired carriage return"),
      UnterminatedBacktick => write!(f, "Unterminated backtick"),
      UnterminatedInterpolation => write!(f, "Unterminated interpolation"),
      UnterminatedString => write!(f, "Unterminated string"),
    }
  }
}
Repository: casey/just
File: tests/misc.rs (Rust)

Code before:
  stderr:   r"
    error: Unterminated interpolation
     ——▶ justfile:2:8
      │
    2 │   echo {{
      │        ^^
  ",
  status:   EXIT_FAILURE,
}

test! {
  name:     unknown_start_of_token,
  justfile: "
assembly_source_files = %(wildcard src/arch/$(arch)/*.s)
",
  stderr:   r"
    error: Unknown start of token '%':
     ——▶ justfile:1:25
      │
    1 │ assembly_source_files = %(wildcard src/arch/$(arch)/*.s)
      │                         ^
  ",
   status:   EXIT_FAILURE,
}

test! {
  name:     unknown_start_of_token_invisible_unicode,
  justfile: "
\u{200b}foo := 'bar'
",
  stderr:   "
error: Unknown start of token '\u{200b}' (U+200B):
 ——▶ justfile:1:1
  │
1 │ \u{200b}foo := 'bar'
  │ ^
",
   status:   EXIT_FAILURE,
}

test! {
  name:     unknown_start_of_token_ascii_control_char,
  justfile: "
\0foo := 'bar'
",
  stderr:   "
error: Unknown start of token '\0' (U+0000):
 ——▶ justfile:1:1
  │
1 │ \0foo := 'bar'
  │ ^

Review comment (suggestion):
Sorry I didn't catch this before: The `test!` macro is kind of deprecated. I don't think it's very clear, and it's often inflexible, so anything custom often requires workarounds, so I try to use the `Test` struct and constructor for new tests (which the `test!` macro uses under the hood). So these should be converted to use the `Test` struct.

Code after:
  name:     unterminated_interpolation_eof,
  justfile: "
    foo:
      echo {{
  ",
  stderr:   r"
    error: Unterminated interpolation
     ——▶ justfile:2:8
      │
    2 │   echo {{
      │        ^^
  ",
  status:   EXIT_FAILURE,
}

#[test]
fn unknown_start_of_token() {
  Test::new()
    .justfile(
      "
assembly_source_files = %(wildcard src/arch/$(arch)/*.s)
      ",
    )
    .stderr(
      r"
    error: Unknown start of token '%'
     ——▶ justfile:1:25
      │
    1 │ assembly_source_files = %(wildcard src/arch/$(arch)/*.s)
      │                         ^
  ",
    )
    .status(EXIT_FAILURE)
    .run();
}

#[test]
fn unknown_start_of_token_invisible_unicode() {
  Test::new()
    .justfile(
      "
\u{200b}foo := 'bar'
      ",
    )
    .stderr(
      "
error: Unknown start of token '\u{200b}' (U+200B)
 ——▶ justfile:1:1
  │
1 │ \u{200b}foo := 'bar'
  │ ^
Repository: casey/just
File: tests/attributes.rs (Rust)

Code before:
",
    )
    .status(EXIT_FAILURE)
    .run();
}

#[test]
fn shell_expanded_strings_can_be_used_in_attributes() {
  Test::new()
    .justfile(
      "
        [doc(x'foo')]
        bar:
      ",
    )
    .run();
}

#[test]
fn env_attribute_single() {
  Test::new()
    .justfile(
      "
        [env('MY_VAR', 'my_value')]
        foo:
          echo $MY_VAR
      ",
    )
    .stdout("my_value\n")
    .stderr("echo $MY_VAR\n")
    .run();
}

#[test]
fn env_attribute_multiple() {
  Test::new()
    .justfile(
      "
        [env('VAR1', 'value1')]
        [env('VAR2', 'value 2')]
        foo:
          echo $VAR1 $VAR2
      ",
    )
    .stdout("value1 value 2\n")
    .stderr("echo $VAR1 $VAR2\n")
    .run();
}

#[test]
fn env_attribute_1_arg() {

Review comment (suggestion):
You can make this a quiet line with `@`, since checking the stderr is not very useful, and make the tests noisier.

Code after:
        [doc(x'foo')]
        bar:
      ",
    )
    .success();
}

#[test]
fn env_attribute_single() {
  Test::new()
    .justfile(
      "
        [env('MY_VAR', 'my_value')]
        foo:
          @echo $MY_VAR
      ",
    )
    .stdout("my_value\n")
    .success();
}

#[test]
fn env_attribute_multiple() {
  Test::new()
    .justfile(
      "
        [env('VAR1', 'value1')]
        [env('VAR2', 'value 2')]
        foo:
          @echo $VAR1 $VAR2
      ",
    )
    .stdout("value1 value 2\n")
    .success();
}

#[test]
fn env_attribute_in_recipe_params() {
  Test::new()
    .justfile(
      r#"
[env("foo", "bar")]
baz x=`echo ${foo}.txt`:
    @echo {{x}}
"#,
    )
    .stdout("bar.txt\n")
    .success();
}

#[test]
Repository: casey/just
File: tests/attributes.rs (Rust)

Code before:
          echo $MY_VAR
      ",
    )
    .stdout("my_value\n")
    .stderr("echo $MY_VAR\n")
    .run();
}

#[test]
fn env_attribute_multiple() {
  Test::new()
    .justfile(
      "
        [env('VAR1', 'value1')]
        [env('VAR2', 'value 2')]
        foo:
          echo $VAR1 $VAR2
      ",
    )
    .stdout("value1 value 2\n")
    .stderr("echo $VAR1 $VAR2\n")
    .run();
}

#[test]
fn env_attribute_1_arg() {
  Test::new()
    .justfile(
      "
        [env('MY_VAR')]
        foo:
          echo bar
      ",
    )
    .stderr(
      "
  error: Attribute `env` got 1 argument but takes 2 arguments
   ——▶ justfile:1:2
    │
  1 │ [env('MY_VAR')]
    │  ^^^
",
    )
    .status(EXIT_FAILURE)
    .run();
}

#[test]
fn env_attribute_3_args() {
  Test::new()
    .justfile(

Review comment (suggestion):
```suggestion
fn env_attribute_too_few_arguments() {
```

Code after:
      "
        [env('VAR1', 'value1')]
        [env('VAR2', 'value 2')]
        foo:
          @echo $VAR1 $VAR2
      ",
    )
    .stdout("value1 value 2\n")
    .success();
}

#[test]
fn env_attribute_in_recipe_params() {
  Test::new()
    .justfile(
      r#"
[env("foo", "bar")]
baz x=`echo ${foo}.txt`:
    @echo {{x}}
"#,
    )
    .stdout("bar.txt\n")
    .success();
}

#[test]
fn env_attribute_not_in_env_function() {
  Test::new()
    .justfile(
      r#"

[env("foo", "bar")]
baz:
  @echo {{ env("foo") }}.txt

    "#,
    )
    .stderr(
      r#"
error: Call to function `env` failed: environment variable `foo` not present
 ——▶ justfile:4:12
  │
4 │   @echo {{ env("foo") }}.txt
  │            ^^^

"#,
    )
    .failure();
}

#[test]
Repository: casey/just
File: tests/attributes.rs (Rust)

Code before:

#[test]
fn env_attribute_1_arg() {
  Test::new()
    .justfile(
      "
        [env('MY_VAR')]
        foo:
          echo bar
      ",
    )
    .stderr(
      "
  error: Attribute `env` got 1 argument but takes 2 arguments
   ——▶ justfile:1:2
    │
  1 │ [env('MY_VAR')]
    │  ^^^
",
    )
    .status(EXIT_FAILURE)
    .run();
}

#[test]
fn env_attribute_3_args() {
  Test::new()
    .justfile(
      "
        [env('A', 'B', 'C')]
        foo:
          echo bar
      ",
    )
    .stderr(
      "
  error: Attribute `env` got 3 arguments but takes 2 arguments
   ——▶ justfile:1:2
    │
  1 │ [env('A', 'B', 'C')]
    │  ^^^
",
    )
    .status(EXIT_FAILURE)
    .run();
}


Review comment (suggestion):
```suggestion
fn env_attribute_too_many_arguments() {
```

Code after:
}

#[test]
fn env_attribute_not_in_env_function() {
  Test::new()
    .justfile(
      r#"

[env("foo", "bar")]
baz:
  @echo {{ env("foo") }}.txt

    "#,
    )
    .stderr(
      r#"
error: Call to function `env` failed: environment variable `foo` not present
 ——▶ justfile:4:12
  │
4 │   @echo {{ env("foo") }}.txt
  │            ^^^

"#,
    )
    .failure();
}

#[test]
fn env_attribute_too_few_arguments() {
  Test::new()
    .justfile(
      "
        [env('MY_VAR')]
        foo:
          echo bar
      ",
    )
    .stderr(
      "
  error: Attribute `env` got 1 argument but takes 2 arguments
   ——▶ justfile:1:2
    │
  1 │ [env('MY_VAR')]
    │  ^^^
",
    )
    .failure();
}

#[test]
fn env_attribute_too_many_arguments() {
Repository: celery/celery
File: t/unit/backends/test_mongodb.py (Python)

Code before:
from __future__ import absolute_import, unicode_literals

import datetime
import sys
from pickle import dumps, loads

import pytest
import pytz
try:
    import pymongo
    import bson
except ImportError:
    pymongo = None
    bson = None
from case import ANY, MagicMock, Mock, mock, patch, sentinel, skip
from kombu.exceptions import EncodeError
try:
    from pymongo.errors import ConfigurationError
except ImportError:
    ConfigurationError = None

from celery import states, uuid
from celery.backends.mongodb import InvalidDocument, MongoBackend, Binary
from celery.exceptions import ImproperlyConfigured

COLLECTION = 'taskmeta_celery'
TASK_ID = uuid()
MONGODB_HOST = 'localhost'
MONGODB_PORT = 27017
MONGODB_USER = 'mongo'
MONGODB_PASSWORD = '1234'
MONGODB_DATABASE = 'testing'
MONGODB_COLLECTION = 'collection1'
MONGODB_GROUP_COLLECTION = 'group_collection1'


@skip.unless_module('pymongo')
class test_MongoBackend:


Review comment (suggestion):
I'd probably use https://docs.pytest.org/en/latest/reference.html#pytest-importorskip-ref in the test that needs it:

```
     def fake_mongo_collection_patch(self, monkeypatch):
         bson = pytest.importorskip("bson")
```



Code after:
from __future__ import absolute_import, unicode_literals

import datetime
import sys
from pickle import dumps, loads

import pytest
import pytz
from case import ANY, MagicMock, Mock, mock, patch, sentinel, skip
from kombu.exceptions import EncodeError
try:
    from pymongo.errors import ConfigurationError
except ImportError:
    ConfigurationError = None

from celery import states, uuid
from celery.backends.mongodb import InvalidDocument, MongoBackend, Binary
from celery.exceptions import ImproperlyConfigured

COLLECTION = 'taskmeta_celery'
TASK_ID = uuid()
MONGODB_HOST = 'localhost'
MONGODB_PORT = 27017
MONGODB_USER = 'mongo'
MONGODB_PASSWORD = '1234'
MONGODB_DATABASE = 'testing'
MONGODB_COLLECTION = 'collection1'
MONGODB_GROUP_COLLECTION = 'group_collection1'


@skip.unless_module('pymongo')
class test_MongoBackend:

    default_url = 'mongodb://uuuu:pwpw@hostname.dom/database'
    replica_set_url = (
        'mongodb://uuuu:pwpw@hostname.dom,'
        'hostname.dom/database?replicaSet=rs'
    )
    sanitized_default_url = 'mongodb://uuuu:**@hostname.dom/database'