Trees | Indices | Help |
---|
|
1 import re 2 from six.moves.urllib.parse import urlparse 3 4 import flask 5 import wtforms 6 import json 7 8 from flask_wtf.file import FileRequired, FileField 9 from fnmatch import fnmatch 10 11 try: # get rid of deprecation warning with newer flask_wtf 12 from flask_wtf import FlaskForm 13 except ImportError: 14 from flask_wtf import Form as FlaskForm 15 16 from coprs import constants 17 from coprs import app 18 from coprs import helpers 19 from coprs import models 20 from coprs.logic.coprs_logic import CoprsLogic, MockChrootsLogic 21 from coprs.logic.users_logic import UsersLogic 22 from coprs.logic.dist_git_logic import DistGitLogic 23 from coprs import exceptions 24 25 from wtforms import ValidationError 26 27 FALSE_VALUES = {False, "false", ""}31 """ 32 Params 33 ------ 34 source_type_text : str 35 name of the source type (scm/pypi/rubygems/git_and_tito/mock_scm) 36 37 Returns 38 ------- 39 BasePackageForm child 40 based on source_type_text input 41 """ 42 if source_type_text == 'scm': 43 return PackageFormScm 44 elif source_type_text == 'pypi': 45 return PackageFormPyPI 46 elif source_type_text == 'rubygems': 47 return PackageFormRubyGems 48 elif source_type_text == 'git_and_tito': 49 return PackageFormTito # deprecated 50 elif source_type_text == 'mock_scm': 51 return PackageFormMock # deprecated 52 elif source_type_text == "custom": 53 return PackageFormCustom 54 else: 55 raise exceptions.UnknownSourceTypeException("Invalid source type")5659 widget = wtforms.widgets.ListWidget(prefix_label=False) 60 option_widget = wtforms.widgets.CheckboxInput()61648466 if not message: 67 message = ("A list of http[s] URLs separated by whitespace characters" 68 " is needed ('{0}' doesn't seem to be a valid URL).") 69 self.message = message7072 urls = field.data.split() 73 for u in urls: 74 if not self.is_url(u): 75 raise wtforms.ValidationError(self.message.format(u))7687 """ Allows also `repo://` schema"""10389 parsed = urlparse(url) 90 if parsed.scheme not in ["http", "https", "copr"]: 91 return False 92 if not parsed.netloc: 93 return False 94 # copr://username/projectname 95 # ^^ schema ^^ netlock ^^ path 96 if parsed.scheme == "copr": 97 # check if projectname missed 98 path_split = parsed.path.split("/") 99 if len(path_split) < 2 or path_split[1] == "": 100 return False 101 102 return True117107 if not message: 108 message = ("URLs must end with .src.rpm, .nosrc.rpm, or .spec" 109 " ('{0}' doesn't seem to be a valid URL).") 110 super(UrlSrpmListValidator, self).__init__(message)111129121 if not message: 122 message = "You can upload only .src.rpm, .nosrc.rpm, and .spec files" 123 self.message = message124132155134 if not message: 135 if group is None: 136 message = "You already have project named '{}'." 137 else: 138 message = "Group {} ".format(group) + "already have project named '{}'." 139 self.message = message 140 if not user: 141 user = flask.g.user 142 self.user = user 143 self.group = group144146 if self.group: 147 existing = CoprsLogic.exists_for_group( 148 self.group, field.data).first() 149 else: 150 existing = CoprsLogic.exists_for_user( 151 self.user, field.data).first() 152 153 if existing and str(existing.id) != form.id.data: 154 raise wtforms.ValidationError(self.message.format(field.data))168159 if not message: 160 message = "Name must contain only letters, digits, underscores, dashes and dots." 161 self.message = message162170202172 already_enabled = {} 173 for module in form.module_toggle.data.split(","): 174 if module == "": 175 return True 176 177 try: 178 module_name, stream = module.strip().split(":") 179 except ValueError: 180 raise ValidationError( 181 message=( 182 "Module name '{0}' must consist of two parts separated " 183 "with colon, e.g. module:stream" 184 ).format(module)) 185 186 pattern = re.compile(re.compile(r"^([a-zA-Z0-9-_!][^\ ]*)$")) 187 if pattern.match(module_name) is None: 188 raise ValidationError(message=( 189 "Module name '{0}' must contain only letters, digits, " 190 "dashes, underscores.").format(module_name)) 191 192 if module_name in already_enabled: 193 raise ValidationError("Module name '{0}' specified multiple " 194 "times".format(module_name)) 195 else: 196 already_enabled[module_name] = True 197 198 if pattern.match(stream) is None: 199 raise ValidationError(message=( 200 "Stream part of module name '{0}' must contain only " 201 "letters, digits, dashes, underscores.").format(stream))214205 # Allow it to be truly optional and has None value 206 if not field.data: 207 return 208 209 selected = set(field.data.split()) 210 enabled = set(MockChrootsLogic.active_names()) 211 212 if selected - enabled: 213 raise wtforms.ValidationError("Such chroot is not available: {}".format(", ".join(selected - enabled)))217226 243219 if not message: 220 message = "Project's name can not be just number." 221 self.message = message222246256 268248 if not value: 249 return '' 250 # Replace every whitespace string with one newline 251 # Formats ideally for html form filling, use replace('\n', ' ') 252 # to get space-separated values or split() to get list 253 result = value.strip() 254 regex = re.compile(r"\s+") 255 return regex.sub(lambda x: '\n', result)270275272 if value: 273 return helpers.PermissionEnum("request") 274 return helpers.PermissionEnum("nothing")278 279 @staticmethod426 427 def validate_mock_chroots_not_empty(self): 428 have_any = False 429 for c in self.chroots_list: 430 if getattr(self, c).data: 431 have_any = True 432 return have_any 433 434 F.chroots_list = MockChrootsLogic.active_names() 435 F.chroots_list.sort() 436 # sets of chroots according to how we should print them in columns 437 F.chroots_sets = {} 438 for ch in F.chroots_list: 439 checkbox_default = False 440 if mock_chroots and ch in [x.name for x in mock_chroots]: 441 checkbox_default = True 442 443 setattr(F, ch, wtforms.BooleanField(ch, default=checkbox_default, false_values=FALSE_VALUES)) 444 if ch[0] in F.chroots_sets: 445 F.chroots_sets[ch[0]].append(ch) 446 else: 447 F.chroots_sets[ch[0]] = [ch] 448 449 return F 450281 class F(FlaskForm): 282 # also use id here, to be able to find out whether user 283 # is updating a copr if so, we don't want to shout 284 # that name already exists 285 id = wtforms.HiddenField() 286 group_id = wtforms.HiddenField() 287 288 name = wtforms.StringField( 289 "Name", 290 validators=[ 291 wtforms.validators.DataRequired(), 292 NameCharactersValidator(), 293 CoprUniqueNameValidator(user=user, group=group), 294 NameNotNumberValidator() 295 ]) 296 297 homepage = wtforms.StringField( 298 "Homepage", 299 validators=[ 300 wtforms.validators.Optional(), 301 wtforms.validators.URL()]) 302 303 contact = wtforms.StringField( 304 "Contact", 305 validators=[ 306 wtforms.validators.Optional(), 307 EmailOrURL()]) 308 309 description = wtforms.TextAreaField("Description") 310 311 instructions = wtforms.TextAreaField("Instructions") 312 313 delete_after_days = wtforms.IntegerField( 314 "Delete after days", 315 validators=[ 316 wtforms.validators.Optional(), 317 wtforms.validators.NumberRange(min=0, max=60), 318 ], 319 render_kw={'disabled': bool(copr and copr.persistent)}) 320 321 repos = wtforms.TextAreaField( 322 "External Repositories", 323 validators=[UrlRepoListValidator()], 324 filters=[StringListFilter()]) 325 326 initial_pkgs = wtforms.TextAreaField( 327 "Initial packages to build", 328 validators=[ 329 UrlListValidator(), 330 UrlSrpmListValidator()], 331 filters=[StringListFilter()]) 332 333 disable_createrepo = wtforms.BooleanField(default=False, 334 label="Create repositories manually", 335 description="""Repository meta data is normally refreshed 336 after each build. If you want to do this manually, turn 337 this option on.""", 338 false_values=FALSE_VALUES) 339 340 unlisted_on_hp = wtforms.BooleanField( 341 "Project will not be listed on home page", 342 default=False, 343 false_values=FALSE_VALUES) 344 345 persistent = wtforms.BooleanField( 346 "Protect project and its builds against deletion", 347 description="""Project's builds and the project itself 348 cannot be deleted by any means. This option is set once and 349 for all (this option can not be changed after project is 350 created).""", 351 render_kw={'disabled': bool(copr)}, 352 default=False, false_values=FALSE_VALUES) 353 354 auto_prune = wtforms.BooleanField( 355 "Old builds will be deleted automatically", 356 default=True, false_values=FALSE_VALUES, 357 description="""Build will be deleted only if there is a 358 newer build (with respect to package version) and it is 359 older than 14 days""") 360 361 use_bootstrap_container = wtforms.BooleanField( 362 "Enable mock's use_bootstrap_container experimental feature", 363 description="""This will make the build slower but it has an 364 advantage that the dnf _from_ the given chroot will be used 365 to setup the chroot (otherwise host system dnf and rpm is 366 used)""", 367 default=False, 368 false_values=FALSE_VALUES) 369 370 follow_fedora_branching = wtforms.BooleanField( 371 "Follow Fedora branching", 372 description="""When Fedora is branched from rawhide, the 373 respective chroots for the new branch are automatically 374 created for you (as soon as they are available) as rawhide 375 chroot forks.""", 376 default=True, 377 false_values=FALSE_VALUES) 378 379 multilib = wtforms.BooleanField( 380 "Multilib support", 381 description="""When users enable this copr repository on 382 64bit variant of multilib capable architecture (e.g. 383 x86_64), they will be able to install 32bit variants of the 384 packages (e.g. i386 for x86_64 arch)""", 385 default=False, 386 false_values=FALSE_VALUES) 387 388 # Deprecated, use `enable_net` instead 389 build_enable_net = wtforms.BooleanField( 390 "Enable internet access during builds", 391 default=False, false_values=FALSE_VALUES) 392 393 enable_net = wtforms.BooleanField( 394 "Enable internet access during builds", 395 default=False, false_values=FALSE_VALUES) 396 397 module_hotfixes = wtforms.BooleanField( 398 "This repository contains module hotfixes", 399 description="""This will make packages from this project 400 available on along with packages from the active module 401 streams.""", 402 default=False, false_values=FALSE_VALUES) 403 404 @property 405 def selected_chroots(self): 406 selected = [] 407 for ch in self.chroots_list: 408 if getattr(self, ch).data: 409 selected.append(ch) 410 return selected411 412 def validate(self): 413 if not super(F, self).validate(): 414 return False 415 416 if not self.validate_mock_chroots_not_empty(): 417 self.errors["chroots"] = ["At least one chroot must be selected"] 418 return False 419 420 if self.persistent.data and self.delete_after_days.data: 421 self.delete_after_days.errors.append( 422 "'delete after' can not be combined with persistent") 423 return False 424 425 return True453 verify = wtforms.StringField( 454 "Confirm deleting by typing 'yes'", 455 validators=[ 456 wtforms.validators.DataRequired(), 457 wtforms.validators.Regexp( 458 r"^yes$", 459 message="Type 'yes' - without the quotes, lowercase.") 460 ])461 465466 467 # @TODO jkadlcik - rewrite via BaseBuildFormFactory after fe-dev-cloud is back online 468 -class BuildFormRebuildFactory(object):469 @staticmethod499 500 F.chroots_list = list(map(lambda x: x.name, active_chroots)) 501 F.chroots_list.sort() 502 F.chroots_sets = {} 503 for ch in F.chroots_list: 504 setattr(F, ch, wtforms.BooleanField(ch, default=True, false_values=FALSE_VALUES)) 505 if ch[0] in F.chroots_sets: 506 F.chroots_sets[ch[0]].append(ch) 507 else: 508 F.chroots_sets[ch[0]] = [ch] 509 510 return F 511471 class F(FlaskForm): 472 @property 473 def selected_chroots(self): 474 selected = [] 475 for ch in self.chroots_list: 476 if getattr(self, ch).data: 477 selected.append(ch) 478 return selected479 480 memory_reqs = wtforms.IntegerField( 481 "Memory requirements", 482 validators=[ 483 wtforms.validators.NumberRange( 484 min=constants.MIN_BUILD_MEMORY, 485 max=constants.MAX_BUILD_MEMORY)], 486 default=constants.DEFAULT_BUILD_MEMORY) 487 488 timeout = wtforms.IntegerField( 489 "Timeout", 490 validators=[ 491 wtforms.validators.NumberRange( 492 min=constants.MIN_BUILD_TIMEOUT, 493 max=constants.MAX_BUILD_TIMEOUT)], 494 default=constants.DEFAULT_BUILD_TIMEOUT) 495 496 enable_net = wtforms.BooleanField(false_values=FALSE_VALUES) 497 background = wtforms.BooleanField(false_values=FALSE_VALUES) 498 project_dirname = wtforms.StringField(default=None)514 @staticmethod521516 form = BuildFormRebuildFactory.create_form_cls(active_chroots) 517 form.package_name = wtforms.StringField( 518 "Package name", 519 validators=[wtforms.validators.DataRequired()]) 520 return form524 if not string: 525 return string 526 fields = [x.lstrip().rstrip() for x in string.split(',')] 527 return ', '.join(fields)528531 if field.data: 532 string = field.data 533 fields = [x.lstrip().rstrip() for x in string.split(',')] 534 for field in fields: 535 pattern = r'^[a-z0-9-*]+$' 536 if not re.match(pattern, field): 537 raise wtforms.ValidationError('Pattern "{0}" does not match "{1}"'.format(field, pattern)) 538 539 matched = set() 540 all_chroots = MockChrootsLogic.active_names() 541 for chroot in all_chroots: 542 if fnmatch(chroot, field): 543 matched.add(chroot) 544 545 if not matched: 546 raise wtforms.ValidationError('no chroot matched by pattern "{0}"'.format(field)) 547 548 if matched == all_chroots: 549 raise wtforms.ValidationError('patterns are black-listing all chroots')550553 package_name = wtforms.StringField( 554 "Package name", 555 validators=[wtforms.validators.DataRequired()]) 556 webhook_rebuild = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 557 chroot_blacklist = wtforms.StringField( 558 "Chroot blacklist", 559 filters=[cleanup_chroot_blacklist], 560 validators=[ 561 wtforms.validators.Optional(), 562 validate_chroot_blacklist, 563 ], 564 ) 565 max_builds = wtforms.IntegerField( 566 "Max number of builds", 567 description="""Keep only the specified number of the newest-by-id builds 568 (garbage collector is run daily)""", 569 render_kw={'placeholder': 'Optional - integer, e.g. 10, zero/empty disables'}, 570 validators=[ 571 wtforms.validators.Optional(), 572 wtforms.validators.NumberRange(min=0, max=100)], 573 default=None, 574 )575578 scm_type = wtforms.SelectField( 579 "Type", 580 choices=[("git", "Git"), ("svn", "SVN")], 581 default="git") 582 583 clone_url = wtforms.StringField( 584 "Clone url", 585 validators=[ 586 wtforms.validators.DataRequired(), 587 wtforms.validators.URL()]) 588 589 committish = wtforms.StringField( 590 "Committish", 591 validators=[ 592 wtforms.validators.Optional()]) 593 594 subdirectory = wtforms.StringField( 595 "Subdirectory", 596 validators=[ 597 wtforms.validators.Optional()]) 598 599 spec = wtforms.StringField( 600 "Spec File", 601 validators=[ 602 wtforms.validators.Optional(), 603 wtforms.validators.Regexp( 604 r"^.+\.spec$", 605 message="RPM spec file must end with .spec")]) 606 607 srpm_build_method = wtforms.SelectField( 608 "SRPM build method", 609 choices=[(x, x) for x in ["rpkg", "tito", "tito_test", "make_srpm"]], 610 default="rpkg") 611 612 @property622614 return json.dumps({ 615 "type": self.scm_type.data, 616 "clone_url": self.clone_url.data, 617 "subdirectory": self.subdirectory.data, 618 "committish": self.committish.data, 619 "spec": self.spec.data, 620 "srpm_build_method": self.srpm_build_method.data, 621 })625 pypi_package_name = wtforms.StringField( 626 "PyPI package name", 627 validators=[wtforms.validators.DataRequired()]) 628 629 pypi_package_version = wtforms.StringField( 630 "PyPI package version", 631 validators=[ 632 wtforms.validators.Optional(), 633 ]) 634 635 spec_template = wtforms.SelectField( 636 "Spec template", 637 choices=[ 638 ("", "default"), 639 ("fedora", "fedora"), 640 ("epel7", "epel7"), 641 ("mageia", "mageia"), 642 ("pld", "pld"), 643 ], default="") 644 645 python_versions = MultiCheckboxField( 646 'Build for Python', 647 choices=[ 648 ('3', 'python3'), 649 ('2', 'python2') 650 ], 651 default=['3', '2']) 652 653 @property661655 return json.dumps({ 656 "pypi_package_name": self.pypi_package_name.data, 657 "pypi_package_version": self.pypi_package_version.data, 658 "spec_template": self.spec_template.data, 659 "python_versions": self.python_versions.data 660 })664 gem_name = wtforms.StringField( 665 "Gem Name", 666 validators=[wtforms.validators.DataRequired()]) 667 668 @property673676 """ 677 @deprecated 678 """ 679 git_url = wtforms.StringField( 680 "Git URL", 681 validators=[ 682 wtforms.validators.DataRequired(), 683 wtforms.validators.URL()]) 684 685 git_directory = wtforms.StringField( 686 "Git Directory", 687 validators=[ 688 wtforms.validators.Optional()]) 689 690 git_branch = wtforms.StringField( 691 "Git Branch", 692 validators=[ 693 wtforms.validators.Optional()]) 694 695 tito_test = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 696 697 @property707699 return json.dumps({ 700 "type": 'git', 701 "clone_url": self.git_url.data, 702 "committish": self.git_branch.data, 703 "subdirectory": self.git_directory.data, 704 "spec": '', 705 "srpm_build_method": 'tito_test' if self.tito_test.data else 'tito', 706 })710 """ 711 @deprecated 712 """ 713 scm_type = wtforms.SelectField( 714 "SCM Type", 715 choices=[("git", "Git"), ("svn", "SVN")]) 716 717 scm_url = wtforms.StringField( 718 "SCM URL", 719 validators=[ 720 wtforms.validators.DataRequired(), 721 wtforms.validators.URL()]) 722 723 scm_branch = wtforms.StringField( 724 "Git Branch", 725 validators=[ 726 wtforms.validators.Optional()]) 727 728 scm_subdir = wtforms.StringField( 729 "Subdirectory", 730 validators=[ 731 wtforms.validators.Optional()]) 732 733 spec = wtforms.StringField( 734 "Spec File", 735 validators=[ 736 wtforms.validators.Optional(), 737 wtforms.validators.Regexp( 738 r"^.+\.spec$", 739 message="RPM spec file must end with .spec")]) 740 741 @property751754 """ 755 @deprecated 756 """ 757 clone_url = wtforms.StringField( 758 "Clone Url", 759 validators=[wtforms.validators.DataRequired()]) 760 761 branch = wtforms.StringField( 762 "Branch", 763 validators=[wtforms.validators.Optional()]) 764 765 @property775778 if not string: 779 return string 780 781 if string.split('\n')[0].endswith('\r'): 782 # This script is most probably coming from the web-UI, where 783 # web-browsers mistakenly put '\r\n' as EOL; and that would just 784 # mean that the script is not executable (any line can mean 785 # syntax error, but namely shebang would cause 100% fail) 786 string = string.replace('\r\n', '\n') 787 788 # And append newline to have a valid unix file. 789 if not string.endswith('\n'): 790 string += '\n' 791 792 return string793796 script = wtforms.TextAreaField( 797 "Script", 798 validators=[ 799 wtforms.validators.DataRequired(), 800 wtforms.validators.Length( 801 max=4096, 802 message="Maximum script size is 4kB"), 803 ], 804 filters=[cleanup_script], 805 ) 806 807 builddeps = wtforms.StringField( 808 "Build dependencies", 809 validators=[wtforms.validators.Optional()]) 810 811 chroot = wtforms.SelectField( 812 'Mock chroot', 813 choices=[], 814 default='fedora-latest-x86_64', 815 ) 816 817 resultdir = wtforms.StringField( 818 "Result directory", 819 validators=[wtforms.validators.Optional()]) 820848822 super(PackageFormCustom, self).__init__(*args, **kwargs) 823 chroot_objects = models.MockChroot.query.filter(models.MockChroot.is_active).all() 824 825 chroots = [c.name for c in chroot_objects] 826 chroots.sort() 827 chroots = [(name, name) for name in chroots] 828 829 arches = set() 830 for ch in chroot_objects: 831 if ch.os_release == 'fedora': 832 arches.add(ch.arch) 833 834 self.chroot.choices = [] 835 if arches: 836 self.chroot.choices += [('fedora-latest-' + l, 'fedora-latest-' + l) for l in arches] 837 838 self.chroot.choices += chroots839 840 @property859852 form_cls = BaseBuildFormFactory(active_chroots, FlaskForm) 853 form_cls.packages = MultiCheckboxField( 854 "Packages", 855 choices=[(name, name) for name in package_names], 856 default=package_names, 857 validators=[wtforms.validators.DataRequired()]) 858 return form_cls871 872 F.memory_reqs = wtforms.IntegerField( 873 "Memory requirements", 874 validators=[ 875 wtforms.validators.Optional(), 876 wtforms.validators.NumberRange( 877 min=constants.MIN_BUILD_MEMORY, 878 max=constants.MAX_BUILD_MEMORY)], 879 default=constants.DEFAULT_BUILD_MEMORY) 880 881 F.timeout = wtforms.IntegerField( 882 "Timeout", 883 validators=[ 884 wtforms.validators.Optional(), 885 wtforms.validators.NumberRange( 886 min=constants.MIN_BUILD_TIMEOUT, 887 max=constants.MAX_BUILD_TIMEOUT)], 888 default=constants.DEFAULT_BUILD_TIMEOUT) 889 890 F.enable_net = wtforms.BooleanField(false_values=FALSE_VALUES) 891 F.background = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 892 F.project_dirname = wtforms.StringField(default=None) 893 894 # overrides BasePackageForm.package_name and is unused for building 895 F.package_name = wtforms.StringField() 896 897 # fill chroots based on project settings 898 F.chroots_list = [x.name for x in active_chroots] 899 F.chroots_list.sort() 900 F.chroots_sets = {} 901 902 package_chroots = set(F.chroots_list) 903 if package: 904 package_chroots = set([ch.name for ch in package.chroots]) 905 906 for ch in F.chroots_list: 907 default = ch in package_chroots 908 setattr(F, ch, wtforms.BooleanField(ch, default=default, false_values=FALSE_VALUES)) 909 if ch[0] in F.chroots_sets: 910 F.chroots_sets[ch[0]].append(ch) 911 else: 912 F.chroots_sets[ch[0]] = [ch] 913 return F 914 919 927 935 940 945 950863 class F(form): 864 @property 865 def selected_chroots(self): 866 selected = [] 867 for ch in self.chroots_list: 868 if getattr(self, ch).data: 869 selected.append(ch) 870 return selected959 964954 form = BaseBuildFormFactory(active_chroots, FlaskForm) 955 form.pkgs = FileField('srpm', validators=[ 956 FileRequired(), 957 SrpmValidator()]) 958 return form977968 form = BaseBuildFormFactory(active_chroots, FlaskForm) 969 form.pkgs = wtforms.TextAreaField( 970 "Pkgs", 971 validators=[ 972 wtforms.validators.DataRequired(message="URLs to packages are required"), 973 UrlListValidator(), 974 UrlSrpmListValidator()], 975 filters=[StringListFilter()]) 976 return form980 modulemd = FileField("modulemd", validators=[ 981 FileRequired(), 982 # @TODO Validate modulemd.yaml file 983 ]) 984 985 create = wtforms.BooleanField("create", default=True, false_values=FALSE_VALUES) 986 build = wtforms.BooleanField("build", default=True, false_values=FALSE_VALUES)987 995 10051008 class ModuleBuildForm(FlaskForm): 1009 distgit_choices = [x.name for x in DistGitLogic.ordered().all()] 1010 distgit_default = distgit_choices[0] 1011 1012 modulemd = FileField("modulemd") 1013 scmurl = wtforms.StringField() 1014 branch = wtforms.StringField() 1015 1016 distgit = wtforms.SelectField( 1017 'Build against DistGit instance', 1018 choices=[(x, x) for x in distgit_choices], 1019 validators=[DistGitValidator()], 1020 filters=[NoneFilter(distgit_default)], 1021 )1022 1023 return ModuleBuildForm(*args, **kwargs) 10241027 repo_url = wtforms.StringField("repo_url", default='') 1028 api_key = wtforms.StringField("api_key", default='') 102910361039 1040 """ 1041 Validator for editing chroots in project 1042 (adding packages to minimal chroot) 1043 """ 1044 1045 buildroot_pkgs = wtforms.StringField("Packages") 1046 1047 repos = wtforms.TextAreaField('Repos', 1048 validators=[UrlRepoListValidator(), 1049 wtforms.validators.Optional()], 1050 filters=[StringListFilter()]) 1051 1052 comps = FileField("comps_xml") 1053 1054 module_toggle = wtforms.StringField("Enable module", 1055 validators=[ModuleEnableNameValidator()], 1056 filters=[StringWhiteCharactersFilter()] 1057 ) 1058 1059 with_opts = wtforms.StringField("With options") 1060 without_opts = wtforms.StringField("Without options")1061 10661069 comment = wtforms.TextAreaField("Comment")10701073 1074 @staticmethod 1078 1079 builder_default = False 1080 admin_default = False 1081 1082 if permission: 1083 if permission.copr_builder != helpers.PermissionEnum("nothing"): 1084 builder_default = True 1085 if permission.copr_admin != helpers.PermissionEnum("nothing"): 1086 admin_default = True 1087 1088 setattr(F, "copr_builder", 1089 wtforms.BooleanField( 1090 default=builder_default, 1091 false_values=FALSE_VALUES, 1092 filters=[ValueToPermissionNumberFilter()])) 1093 1094 setattr(F, "copr_admin", 1095 wtforms.BooleanField( 1096 default=admin_default, 1097 false_values=FALSE_VALUES, 1098 filters=[ValueToPermissionNumberFilter()])) 1099 1100 return F11011104 1105 """Creates a dynamic form for given set of copr permissions""" 1106 @staticmethod 1110 1111 for perm in permissions: 1112 builder_choices = helpers.PermissionEnum.choices_list() 1113 admin_choices = helpers.PermissionEnum.choices_list() 1114 1115 builder_default = perm.copr_builder 1116 admin_default = perm.copr_admin 1117 1118 setattr(F, "copr_builder_{0}".format(perm.user.id), 1119 wtforms.SelectField( 1120 choices=builder_choices, 1121 default=builder_default, 1122 coerce=int)) 1123 1124 setattr(F, "copr_admin_{0}".format(perm.user.id), 1125 wtforms.SelectField( 1126 choices=admin_choices, 1127 default=admin_default, 1128 coerce=int)) 1129 1130 return F11311134 description = wtforms.TextAreaField('Description', 1135 validators=[wtforms.validators.Optional()]) 1136 1137 instructions = wtforms.TextAreaField('Instructions', 1138 validators=[wtforms.validators.Optional()]) 1139 1140 chroots = wtforms.TextAreaField('Chroots', 1141 validators=[wtforms.validators.Optional(), ChrootsValidator()]) 1142 1143 repos = wtforms.TextAreaField('External Repositories', 1144 validators=[UrlRepoListValidator(), 1145 wtforms.validators.Optional()], 1146 filters=[StringListFilter()]) 1147 1148 disable_createrepo = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1149 unlisted_on_hp = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1150 auto_prune = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1151 use_bootstrap_container = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1152 follow_fedora_branching = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1153 follow_fedora_branching = wtforms.BooleanField(default=True, false_values=FALSE_VALUES) 1154 delete_after_days = wtforms.IntegerField( 1155 validators=[wtforms.validators.Optional(), 1156 wtforms.validators.NumberRange(min=-1, max=60)], 1157 filters=[(lambda x : -1 if x is None else x)]) 1158 1159 # Deprecated, use `enable_net` instead 1160 build_enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1161 enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1162 multilib = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1163 module_hotfixes = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)11641167 @staticmethod11901169 class F(FlaskForm): 1170 source = wtforms.StringField( 1171 "Source", 1172 default=copr.full_name) 1173 1174 owner = wtforms.SelectField( 1175 "Fork owner", 1176 choices=[(user.name, user.name)] + [(g.at_name, g.at_name) for g in groups], 1177 default=user.name, 1178 validators=[wtforms.validators.DataRequired()]) 1179 1180 name = wtforms.StringField( 1181 "Fork name", 1182 default=copr.name, 1183 validators=[wtforms.validators.DataRequired(), NameCharactersValidator()]) 1184 1185 confirm = wtforms.BooleanField( 1186 "Confirm", 1187 false_values=FALSE_VALUES, 1188 default=False)1189 return F1193 buildroot_pkgs = wtforms.StringField('Additional packages to be always present in minimal buildroot') 1194 repos = wtforms.TextAreaField('Additional repos to be used for builds in chroot', 1195 validators=[UrlRepoListValidator(), 1196 wtforms.validators.Optional()], 1197 filters=[StringListFilter()]) 1198 comps = None 1199 upload_comps = FileField("Upload comps.xml") 1200 delete_comps = wtforms.BooleanField("Delete comps.xml", false_values=FALSE_VALUES)12011204 copr_ids = wtforms.SelectMultipleField(wtforms.IntegerField("Pinned Copr ID")) 12051221 12251207 if any([i and not i.isnumeric() for i in self.copr_ids.data]): 1208 self.errors["coprs"] = ["Unexpected value selected"] 1209 return False 1210 1211 limit = app.config["PINNED_PROJECTS_LIMIT"] 1212 if len(self.copr_ids.data) > limit: 1213 self.errors["coprs"] = ["Too many pinned projects. Limit is {}!".format(limit)] 1214 return False 1215 1216 if len(list(filter(None, self.copr_ids.data))) != len(set(filter(None, self.copr_ids.data))): 1217 self.errors["coprs"] = ["You can pin a particular project only once"] 1218 return False 1219 1220 return True1228 project = wtforms.StringField("Project")1229123212411234 if not message: 1235 message = "Group with the alias '{}' already exists." 1236 self.message = message12371239 if UsersLogic.group_alias_exists(field.data): 1240 raise wtforms.ValidationError(self.message.format(field.data))1244 1245 name = wtforms.StringField( 1246 validators=[ 1247 wtforms.validators.Regexp( 1248 re.compile(r"^[\w.-]+$"), 1249 message="Name must contain only letters," 1250 "digits, underscores, dashes and dots."), 1251 GroupUniqueNameValidator() 1252 ] 1253 )12541257 builds = wtforms.FieldList(wtforms.StringField("Builds ID list")) 1258 packages = wtforms.FieldList(wtforms.StringField("Packages list")) 1259 filter = wtforms.FieldList(wtforms.StringField("Package Filter")) 1260 api = wtforms.FieldList(wtforms.StringField("Module API")) 1261 profile_names = wtforms.FieldList(wtforms.StringField("Install Profiles"), min_entries=2) 1262 profile_pkgs = wtforms.FieldList(wtforms.FieldList(wtforms.StringField("Install Profiles")), min_entries=2) 1263 126712881269 if not FlaskForm.validate(self): 1270 return False 1271 1272 # Profile names should be unique 1273 names = [x for x in self.profile_names.data if x] 1274 if len(set(names)) < len(names): 1275 self.errors["profiles"] = ["Profile names must be unique"] 1276 return False 1277 1278 # WORKAROUND 1279 # profile_pkgs are somehow sorted so if I fill profile_name in the first box and 1280 # profile_pkgs in seconds box, it is sorted and validated correctly 1281 for i in range(0, len(self.profile_names.data)): 1282 # If profile name is not set, then there should not be any packages in this profile 1283 if not flask.request.form["profile_names-{}".format(i)]: 1284 if [j for j in range(0, len(self.profile_names)) if "profile_pkgs-{}-{}".format(i, j) in flask.request.form]: 1285 self.errors["profiles"] = ["Missing profile name"] 1286 return False 1287 return True1291 owner = wtforms.StringField("Owner Name", validators=[wtforms.validators.DataRequired()]) 1292 copr = wtforms.StringField("Copr Name", validators=[wtforms.validators.DataRequired()]) 1293 name = wtforms.StringField("Name", validators=[wtforms.validators.DataRequired()]) 1294 stream = wtforms.StringField("Stream", validators=[wtforms.validators.DataRequired()]) 1295 version = wtforms.IntegerField("Version", validators=[wtforms.validators.DataRequired()]) 1296 arch = wtforms.StringField("Arch", validators=[wtforms.validators.DataRequired()])1297
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 | http://epydoc.sourceforge.net |