def __str__(self): content = [ get_override_warning_banner(), '', ] if len(self): for k, v in self: v = textwrap.dedent(str(v)).strip() v = v.replace('\n', ' \\\n' + ' ' * (len(k) + 4)) content.append('{} {} {}'.format( k, self._env_assignment_operators.get(k, '?='), v)) content.append('') if len(self.phony): content.append('.PHONY: ' + ' '.join(sorted(self.phony))) content.append('') for target, details in self.targets: deps, rule, doc = details content.append('{}: {} ## {}'.format( target, ' '.join(deps), doc.replace('\n', ' ') if doc else '').strip()) script = textwrap.dedent(str(rule)).strip() for line in script.split('\n'): content.append('\t' + line) content.append('') return '\n'.join(content)
def __str__(self): content = [get_override_warning_banner(), ""] + self.header + [""] if len(self): for k, v in self: v = textwrap.dedent(str(v)).strip() v = v.replace("\n", " \\\n" + " " * (len(k) + 4)) content.append("{} {} {}".format(k, self._env_assignment_operators.get(k, "?="), v)) content.append("") if len(self.phony): content.append(".PHONY: " + " ".join(sorted(self.phony))) content.append("") for target, details in self.targets: deps, rule, doc = details if hasattr(rule, "render"): content += list(rule.render(target, deps, doc)) else: content.append( "{}: {} {} {}".format( target, " ".join(deps), "#" if target in self.hidden else "##", doc.replace("\n", " ") if doc else "", ).strip() ) script = textwrap.dedent(str(rule)).strip() for line in script.split("\n"): content.append("\t" + line) content.append("") return "\n".join(content)
def on_start(self, event): """ **Events** - ``medikit.feature.python.on_generate`` (with the same ``ProjectEvent`` we got, todo: why not deprecate it in favor of higher priority medikit.on_start?) **Files** - ``<yourpackage>/__init__.py`` - ``MANIFEST.in`` - ``README.rst`` - ``classifiers.txt`` - ``requirements-dev.txt`` - ``requirements.txt`` - ``setup.cfg`` - ``setup.py`` (overwritten) :param ProjectEvent event: """ self.dispatcher.dispatch(__name__ + ".on_generate", event) # Our config object python_config = event.config["python"] # Some metadata that will prove useful. self.render_empty_files("classifiers.txt", "README.rst") self.render_file_inline("MANIFEST.in", "include *.txt") with event.config.define_resource(ConfigParserResource, "setup.cfg") as setup_cfg: setup_cfg.set_initial_values({ "bdist_wheel": { "universal": "1" }, "metadata": { "description-file": "README.rst" } }) # XXX there is an important side effect in get_init_files that defines namespace packages for later use in # setup.py rendering. Even if we do not want to create the packages here, it is important to make the call # anyway. for dirname, filename, context in python_config.get_init_files(): if python_config.create_packages: if not os.path.exists(dirname): os.makedirs(dirname) self.render_file(filename, "python/package_init.py.j2", context) # render version file, try to import version from version.txt if available. try: with open("version.txt") as f: version = f.read().strip() except IOError: version = "0.0.0" self.render_file_inline(python_config.version_file, "__version__ = '{}'".format(version)) setup = python_config.get_setup() context = { "url": setup.pop("url", "http://example.com/"), "download_url": setup.pop("download_url", "http://example.com/"), } for k, v in context.items(): context[k] = context[k].format(name=setup["name"], user=getuser(), version="{version}") context.update({ "entry_points": setup.pop("entry_points", {}), "extras_require": python_config.get("extras_require"), "install_requires": python_config.get("install_requires"), "python": python_config, "setup": setup, "banner": get_override_warning_banner(), }) # Render (with overwriting) the allmighty setup.py self.render_file("setup.py", "python/setup.py.j2", context, override=True)
def on_start(self, event): """ **Events** - ``medikit.feature.python.on_generate`` (with the same ``ProjectEvent`` we got, todo: why not deprecate it in favor of higher priority medikit.on_start?) **Files** - ``<yourpackage>/__init__.py`` - ``MANIFEST.in`` - ``README.rst`` - ``classifiers.txt`` - ``requirements-dev.txt`` - ``requirements.txt`` - ``setup.cfg`` - ``setup.py`` (overwritten) :param ProjectEvent event: """ self.dispatcher.dispatch(__name__ + ".on_generate", event) # Our config object python_config = event.config["python"] # Some metadata that will prove useful. self.render_empty_files("classifiers.txt", "README.rst") self.render_file_inline("MANIFEST.in", "include *.txt") self.render_file_inline( "setup.cfg", """ [bdist_wheel] # This flag says that the code is written to work on both Python 2 and Python # 3. If at all possible, it is good practice to do this. If you cannot, you # will need to generate wheels for each Python version that you support. universal=1 [metadata] description-file = README.rst """, ) # XXX there is an important side effect in get_init_files that defines namespace packages for later use in # setup.py rendering. Even if we do not want to create the packages here, it is important to make the call # anyway. for dirname, filename, context in python_config.get_init_files(): if python_config.create_packages: if not os.path.exists(dirname): os.makedirs(dirname) self.render_file(filename, "python/package_init.py.j2", context) # render version file, try to import version from version.txt if available. try: with open("version.txt") as f: version = f.read().strip() except IOError: version = "0.0.0" self.render_file_inline(python_config.version_file, "__version__ = '{}'".format(version)) setup = python_config.get_setup() context = { "url": setup.pop("url", "http://example.com/"), "download_url": setup.pop("download_url", "http://example.com/"), } for k, v in context.items(): context[k] = context[k].format(name=setup["name"], user=getuser(), version="{version}") context.update( { "entry_points": setup.pop("entry_points", {}), "extras_require": python_config.get("extras_require"), "install_requires": python_config.get("install_requires"), "python": python_config, "setup": setup, "banner": get_override_warning_banner(), } ) # Render (with overwriting) the allmighty setup.py self.render_file("setup.py", "python/setup.py.j2", context, override=True)
def on_end(self, event): # Our config object python_config = event.config["python"] # Pip / PyPI repository = PyPIRepository([], cache_dir=CACHE_DIR) # We just need to construct this structure if use_uniform_requirements == True requirements_by_name = {} if python_config.use_uniform_requirements: tmpfile = tempfile.NamedTemporaryFile(mode="wt", delete=False) for extra in itertools.chain((None,), python_config.get_extras()): tmpfile.write("\n".join(python_config.get_requirements(extra=extra)) + "\n") tmpfile.flush() constraints = list( parse_requirements( tmpfile.name, finder=repository.finder, session=repository.session, options=repository.options ) ) # This resolver is able to evaluate ALL the dependencies along the extras resolver = Resolver( constraints, repository, cache=DependencyCache(CACHE_DIR), # cache=DependencyCache(tempfile.tempdir), prereleases=False, clear_caches=False, allow_unsafe=False, ) for req in resolver.resolve(max_rounds=10): requirements_by_name[parse_requirement(str(req.req)).name] = SimpleNamespace( requirement=format_requirement(req).strip().replace(" ", ""), url=req.link ) python_config.check_duplicate_dependencies_uniform(requirements_by_name) # Now it iterates along the versions in extras and looks for the requirements and its dependencies, using the # structure created above to select the unified versions (unless the flag indicates otherwise). for extra in itertools.chain((None,), python_config.get_extras()): requirements_file = "requirements{}.txt".format("-" + extra if extra else "") if python_config.override_requirements or not os.path.exists(requirements_file): tmpfile = tempfile.NamedTemporaryFile(mode="wt", delete=False) tmpfile.write("\n".join(python_config.get_requirements(extra=extra)) + "\n") tmpfile.flush() constraints = list( parse_requirements( tmpfile.name, finder=repository.finder, session=repository.session, options=repository.options ) ) resolver = Resolver( constraints, repository, cache=DependencyCache(CACHE_DIR), prereleases=False, clear_caches=False, allow_unsafe=False, ) if not python_config.use_uniform_requirements: python_config.check_duplicate_dependencies_nonuniform(extra, resolver) requirements_list = [] for req in resolver.resolve(max_rounds=10): if req.name != python_config.get("name"): requirement = python_config.get_requirement_info_by_name(req, requirements_by_name) if requirement: requirements_list.append(requirement) self.render_file_inline( requirements_file, "\n".join( ( "-e .{}".format("[" + extra + "]" if extra else ""), *(("-r requirements.txt",) if extra else ()), *python_config.get_vendors(extra=extra), *sorted(requirements_list), ) ), override=python_config.override_requirements, ) # Updates setup file setup = python_config.get_setup() context = { "url": setup.pop("url", ""), "download_url": setup.pop("download_url", ""), } for k, v in context.items(): context[k] = context[k].format(name=setup["name"], user=getuser(), version="{version}") context.update( { "entry_points": setup.pop("entry_points", {}), "extras_require": python_config.get("extras_require"), "install_requires": python_config.get("install_requires"), "python": python_config, "setup": setup, "banner": get_override_warning_banner(), } ) # Render (with overwriting) the allmighty setup.py self.render_file("setup.py", "python/setup.py.j2", context, override=True)
def on_start(self, event): """ **Events** - ``medikit.feature.python.on_generate`` (with the same ``ProjectEvent`` we got, todo: why not deprecate it in favor of higher priority medikit.on_start?) **Files** - ``<yourpackage>/__init__.py`` - ``MANIFEST.in`` - ``README.rst`` - ``classifiers.txt`` - ``requirements-dev.txt`` - ``requirements.txt`` - ``setup.cfg`` - ``setup.py`` (overwritten) :param ProjectEvent event: """ self.dispatcher.dispatch(__name__ + '.on_generate', event) # Our config object python_config = event.config['python'] # Some metadata that will prove useful. self.render_empty_files('classifiers.txt', 'README.rst') self.render_file_inline('MANIFEST.in', 'include *.txt') self.render_file_inline( 'setup.cfg', ''' [bdist_wheel] # This flag says that the code is written to work on both Python 2 and Python # 3. If at all possible, it is good practice to do this. If you cannot, you # will need to generate wheels for each Python version that you support. universal=1 [metadata] description-file = README.rst ''' ) # XXX there is an important side effect in get_init_files that defines namespace packages for later use in # setup.py rendering. Even if we do not want to create the packages here, it is important to make the call # anyway. for dirname, filename, context in python_config.get_init_files(): if python_config.create_packages: if not os.path.exists(dirname): os.makedirs(dirname) self.render_file(filename, 'python/package_init.py.j2', context) # render version file, try to import version from version.txt if available. try: with open('version.txt') as f: version = f.read().strip() except IOError: version = '0.0.0' self.render_file_inline(python_config.version_file, "__version__ = '{}'".format(version)) setup = python_config.get_setup() context = { 'url': setup.pop('url', 'http://example.com/'), 'download_url': setup.pop('download_url', 'http://example.com/'), } for k, v in context.items(): context[k] = context[k].format( name=setup['name'], user=getuser(), version='{version}', ) context.update( { 'entry_points': setup.pop('entry_points', {}), 'extras_require': python_config.get('extras_require'), 'install_requires': python_config.get('install_requires'), 'python': python_config, 'setup': setup, 'banner': get_override_warning_banner(), } ) # Render (with overwriting) the allmighty setup.py self.render_file('setup.py', 'python/setup.py.j2', context, override=True)