public static function fromString($constraintExpression)
    {
        if (!preg_match('/^(==?|\!=?|~|[<>]=?)?((?:\*|[0-9]+)(?:.(?:\*|[0-9]+))*)(?:\@(\w+))?$/', $constraintExpression, $m)) {
            throw new \InvalidArgumentException("Constraint expression '$constraintExpression' could not be parsed");
        }
        return new self(
            !empty($m[1]) ? $m[1] : '=',
            $m[2],
            !empty($m[3]) ? $m[3] : 'stable'
        );
    }