Question: How can we assign a theme in Magento 2.1 to a store using setup scripts?

Thank you

Answer: 
Create a new *InstallData* (or *UpgradeData*) script in either a new module or a fitting pre-existing module.

Here is a simple example for a complete `InstallData` script. Simply replace the `THEME_NAME` constant found at the top of the class with your own theme name. For example, if you wanted to assign the default Magento 2 luma theme, you would write:

```
const THEME_NAME = 'Magento/luma';

```

*(Make sure the **V**endor starts with an uppercase and the **t**heme with a lower case letter!)*

You can find your theme name by simply looking at the `registration.php` in the directory of your theme (found in *app/design/frontend/*), it's probably easiest to copy paste it from here to prevent any typos:

```
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::THEME,
    'frontend/Vendor/theme',
    __DIR__
);

```

The full `InstallData.php` script looks like this, alternatively you can add it to an `UpgradeData.php` as well, you mainly need the assignTheme() method from the bottom and inject all the required classes into the constructor:

```
<?php
namespace Medline\Theme\Setup;

use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\Store;

/**
 * @codeCoverageIgnore
 * @SuppressWarnings(PHPMD)
 */
class InstallData implements InstallDataInterface
{
    const THEME_NAME = 'Vendor/theme';

    /**
     * @var \Magento\Theme\Model\Config
     */
    private $config;

    /**
     * @var \Magento\Theme\Model\ResourceModel\Theme\CollectionFactory
     */
    private $collectionFactory;

    /**
     * InstallData constructor.
     * @param \Magento\Theme\Model\ResourceModel\Theme\CollectionFactory $collectionFactory
     * @param \Magento\Theme\Model\Config $config
     */
    public function __construct(
        \Magento\Theme\Model\ResourceModel\Theme\CollectionFactory $collectionFactory,
        \Magento\Theme\Model\Config $config
    ) {
        $this->collectionFactory = $collectionFactory;
        $this->config = $config;
    }

    /**
     * @param ModuleDataSetupInterface $setup
     * @param ModuleContextInterface $context
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();

        $this->assignTheme();

        $setup->endSetup();
    }

    /**
     * Assign Theme
     *
     * @return void
     */
    protected function assignTheme()
    {
        $themes = $this->collectionFactory->create()->loadRegisteredThemes();
        /**
         * @var \Magento\Theme\Model\Theme $theme
         */
        foreach ($themes as $theme) {
            if ($theme->getCode() == self::THEME_NAME) {
                $this->config->assignToStore(
                    $theme,
                    [Store::DEFAULT_STORE_ID],
                    ScopeConfigInterface::SCOPE_TYPE_DEFAULT
                );
            }
        }
    }
}

```
Above solutions work but have one shortcoming.
They assume that magento has already registered the theme, before setup script execution.
This is not always the case. If you revert entries in `setup_module` table, you discover that error is "magically fixed".

To avoid it, make sure that themes are registered before setup script execution.
One way to do it is 

```
\Magento\Theme\Model\Theme\Registration::register()

```