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 import exceptions 23 24 25 FALSE_VALUES = {False, "false", ""}29 """ 30 Params 31 ------ 32 source_type_text : str 33 name of the source type (scm/pypi/rubygems/git_and_tito/mock_scm) 34 35 Returns 36 ------- 37 BasePackageForm child 38 based on source_type_text input 39 """ 40 if source_type_text == 'scm': 41 return PackageFormScm 42 elif source_type_text == 'pypi': 43 return PackageFormPyPI 44 elif source_type_text == 'rubygems': 45 return PackageFormRubyGems 46 elif source_type_text == 'git_and_tito': 47 return PackageFormTito # deprecated 48 elif source_type_text == 'mock_scm': 49 return PackageFormMock # deprecated 50 elif source_type_text == "custom": 51 return PackageFormCustom 52 else: 53 raise exceptions.UnknownSourceTypeException("Invalid source type")5457 widget = wtforms.widgets.ListWidget(prefix_label=False) 58 option_widget = wtforms.widgets.CheckboxInput()59628264 if not message: 65 message = ("A list of http[s] URLs separated by whitespace characters" 66 " is needed ('{0}' doesn't seem to be a valid URL).") 67 self.message = message6870 urls = field.data.split() 71 for u in urls: 72 if not self.is_url(u): 73 raise wtforms.ValidationError(self.message.format(u))7485 """ Allows also `repo://` schema"""10187 parsed = urlparse(url) 88 if parsed.scheme not in ["http", "https", "copr"]: 89 return False 90 if not parsed.netloc: 91 return False 92 # copr://username/projectname 93 # ^^ schema ^^ netlock ^^ path 94 if parsed.scheme == "copr": 95 # check if projectname missed 96 path_split = parsed.path.split("/") 97 if len(path_split) < 2 or path_split[1] == "": 98 return False 99 100 return True115105 if not message: 106 message = ("URLs must end with .src.rpm, .nosrc.rpm, or .spec" 107 " ('{0}' doesn't seem to be a valid URL).") 108 super(UrlSrpmListValidator, self).__init__(message)109127119 if not message: 120 message = "You can upload only .src.rpm, .nosrc.rpm, and .spec files" 121 self.message = message122130153132 if not message: 133 if group is None: 134 message = "You already have project named '{}'." 135 else: 136 message = "Group {} ".format(group) + "already have project named '{}'." 137 self.message = message 138 if not user: 139 user = flask.g.user 140 self.user = user 141 self.group = group142144 if self.group: 145 existing = CoprsLogic.exists_for_group( 146 self.group, field.data).first() 147 else: 148 existing = CoprsLogic.exists_for_user( 149 self.user, field.data).first() 150 151 if existing and str(existing.id) != form.id.data: 152 raise wtforms.ValidationError(self.message.format(field.data))166157 if not message: 158 message = "Name must contain only letters, digits, underscores, dashes and dots." 159 self.message = message160179170 # Allow it to be truly optional and has None value 171 if not field.data: 172 return 173 174 selected = set(field.data.split()) 175 enabled = set(MockChrootsLogic.active_names()) 176 177 if selected - enabled: 178 raise wtforms.ValidationError("Such chroot is not available: {}".format(", ".join(selected - enabled)))182191 208184 if not message: 185 message = "Project's name can not be just number." 186 self.message = message187211221213 if not value: 214 return '' 215 # Replace every whitespace string with one newline 216 # Formats ideally for html form filling, use replace('\n', ' ') 217 # to get space-separated values or split() to get list 218 result = value.strip() 219 regex = re.compile(r"\s+") 220 return regex.sub(lambda x: '\n', result)224229226 if value: 227 return helpers.PermissionEnum("request") 228 return helpers.PermissionEnum("nothing")232 233 @staticmethod364 365 def validate_mock_chroots_not_empty(self): 366 have_any = False 367 for c in self.chroots_list: 368 if getattr(self, c).data: 369 have_any = True 370 return have_any 371 372 F.chroots_list = MockChrootsLogic.active_names() 373 F.chroots_list.sort() 374 # sets of chroots according to how we should print them in columns 375 F.chroots_sets = {} 376 for ch in F.chroots_list: 377 checkbox_default = False 378 if mock_chroots and ch in [x.name for x in mock_chroots]: 379 checkbox_default = True 380 381 setattr(F, ch, wtforms.BooleanField(ch, default=checkbox_default, false_values=FALSE_VALUES)) 382 if ch[0] in F.chroots_sets: 383 F.chroots_sets[ch[0]].append(ch) 384 else: 385 F.chroots_sets[ch[0]] = [ch] 386 387 return F 388235 class F(FlaskForm): 236 # also use id here, to be able to find out whether user 237 # is updating a copr if so, we don't want to shout 238 # that name already exists 239 id = wtforms.HiddenField() 240 group_id = wtforms.HiddenField() 241 242 name = wtforms.StringField( 243 "Name", 244 validators=[ 245 wtforms.validators.DataRequired(), 246 NameCharactersValidator(), 247 CoprUniqueNameValidator(user=user, group=group), 248 NameNotNumberValidator() 249 ]) 250 251 homepage = wtforms.StringField( 252 "Homepage", 253 validators=[ 254 wtforms.validators.Optional(), 255 wtforms.validators.URL()]) 256 257 contact = wtforms.StringField( 258 "Contact", 259 validators=[ 260 wtforms.validators.Optional(), 261 EmailOrURL()]) 262 263 description = wtforms.TextAreaField("Description") 264 265 instructions = wtforms.TextAreaField("Instructions") 266 267 delete_after_days = wtforms.IntegerField( 268 "Delete after days", 269 validators=[ 270 wtforms.validators.Optional(), 271 wtforms.validators.NumberRange(min=0, max=60), 272 ], 273 render_kw={'disabled': bool(copr and copr.persistent)}) 274 275 repos = wtforms.TextAreaField( 276 "External Repositories", 277 validators=[UrlRepoListValidator()], 278 filters=[StringListFilter()]) 279 280 initial_pkgs = wtforms.TextAreaField( 281 "Initial packages to build", 282 validators=[ 283 UrlListValidator(), 284 UrlSrpmListValidator()], 285 filters=[StringListFilter()]) 286 287 disable_createrepo = wtforms.BooleanField(default=False, 288 label="Create repositories manually", 289 description="""Repository meta data is normally refreshed 290 after each build. If you want to do this manually, turn 291 this option on.""", 292 false_values=FALSE_VALUES) 293 294 unlisted_on_hp = wtforms.BooleanField( 295 "Project will not be listed on home page", 296 default=False, 297 false_values=FALSE_VALUES) 298 299 persistent = wtforms.BooleanField( 300 "Protect project and its builds against deletion", 301 description="""Project's builds and the project itself 302 cannot be deleted by any means. This option is set once and 303 for all (this option can not be changed after project is 304 created).""", 305 render_kw={'disabled': bool(copr)}, 306 default=False, false_values=FALSE_VALUES) 307 308 auto_prune = wtforms.BooleanField( 309 "Old builds will be deleted automatically", 310 default=True, false_values=FALSE_VALUES, 311 description="""Build will be deleted only if there is a 312 newer build (with respect to package version) and it is 313 older than 14 days""") 314 315 use_bootstrap_container = wtforms.BooleanField( 316 "Enable mock's use_bootstrap_container experimental feature", 317 description="""This will make the build slower but it has an 318 advantage that the dnf _from_ the given chroot will be used 319 to setup the chroot (otherwise host system dnf and rpm is 320 used)""", 321 default=False, 322 false_values=FALSE_VALUES) 323 324 follow_fedora_branching = wtforms.BooleanField( 325 "Follow Fedora branching", 326 description="""When Fedora is branched from rawhide, the 327 respective chroots for the new branch are automatically 328 created for you (as soon as they are available) as rawhide 329 chroot forks.""", 330 default=True, 331 false_values=FALSE_VALUES) 332 333 # Deprecated, use `enable_net` instead 334 build_enable_net = wtforms.BooleanField( 335 "Enable internet access during builds", 336 default=False, false_values=FALSE_VALUES) 337 338 enable_net = wtforms.BooleanField( 339 "Enable internet access during builds", 340 default=False, false_values=FALSE_VALUES) 341 342 @property 343 def selected_chroots(self): 344 selected = [] 345 for ch in self.chroots_list: 346 if getattr(self, ch).data: 347 selected.append(ch) 348 return selected349 350 def validate(self): 351 if not super(F, self).validate(): 352 return False 353 354 if not self.validate_mock_chroots_not_empty(): 355 self.errors["chroots"] = ["At least one chroot must be selected"] 356 return False 357 358 if self.persistent.data and self.delete_after_days.data: 359 self.delete_after_days.errors.append( 360 "'delete after' can not be combined with persistent") 361 return False 362 363 return True391 verify = wtforms.StringField( 392 "Confirm deleting by typing 'yes'", 393 validators=[ 394 wtforms.validators.DataRequired(), 395 wtforms.validators.Regexp( 396 r"^yes$", 397 message="Type 'yes' - without the quotes, lowercase.") 398 ])399 403404 405 # @TODO jkadlcik - rewrite via BaseBuildFormFactory after fe-dev-cloud is back online 406 -class BuildFormRebuildFactory(object):407 @staticmethod437 438 F.chroots_list = list(map(lambda x: x.name, active_chroots)) 439 F.chroots_list.sort() 440 F.chroots_sets = {} 441 for ch in F.chroots_list: 442 setattr(F, ch, wtforms.BooleanField(ch, default=True, false_values=FALSE_VALUES)) 443 if ch[0] in F.chroots_sets: 444 F.chroots_sets[ch[0]].append(ch) 445 else: 446 F.chroots_sets[ch[0]] = [ch] 447 448 return F 449409 class F(FlaskForm): 410 @property 411 def selected_chroots(self): 412 selected = [] 413 for ch in self.chroots_list: 414 if getattr(self, ch).data: 415 selected.append(ch) 416 return selected417 418 memory_reqs = wtforms.IntegerField( 419 "Memory requirements", 420 validators=[ 421 wtforms.validators.NumberRange( 422 min=constants.MIN_BUILD_MEMORY, 423 max=constants.MAX_BUILD_MEMORY)], 424 default=constants.DEFAULT_BUILD_MEMORY) 425 426 timeout = wtforms.IntegerField( 427 "Timeout", 428 validators=[ 429 wtforms.validators.NumberRange( 430 min=constants.MIN_BUILD_TIMEOUT, 431 max=constants.MAX_BUILD_TIMEOUT)], 432 default=constants.DEFAULT_BUILD_TIMEOUT) 433 434 enable_net = wtforms.BooleanField(false_values=FALSE_VALUES) 435 background = wtforms.BooleanField(false_values=FALSE_VALUES) 436 project_dirname = wtforms.StringField(default=None)452 @staticmethod459454 form = BuildFormRebuildFactory.create_form_cls(active_chroots) 455 form.package_name = wtforms.StringField( 456 "Package name", 457 validators=[wtforms.validators.DataRequired()]) 458 return form462 if not string: 463 return string 464 fields = [x.lstrip().rstrip() for x in string.split(',')] 465 return ', '.join(fields)466469 if field.data: 470 string = field.data 471 fields = [x.lstrip().rstrip() for x in string.split(',')] 472 for field in fields: 473 pattern = r'^[a-z0-9-*]+$' 474 if not re.match(pattern, field): 475 raise wtforms.ValidationError('Pattern "{0}" does not match "{1}"'.format(field, pattern)) 476 477 matched = set() 478 all_chroots = MockChrootsLogic.active_names() 479 for chroot in all_chroots: 480 if fnmatch(chroot, field): 481 matched.add(chroot) 482 483 if not matched: 484 raise wtforms.ValidationError('no chroot matched by pattern "{0}"'.format(field)) 485 486 if matched == all_chroots: 487 raise wtforms.ValidationError('patterns are black-listing all chroots')488491 package_name = wtforms.StringField( 492 "Package name", 493 validators=[wtforms.validators.DataRequired()]) 494 webhook_rebuild = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 495 chroot_blacklist = wtforms.StringField( 496 "Chroot blacklist", 497 filters=[cleanup_chroot_blacklist], 498 validators=[ 499 wtforms.validators.Optional(), 500 validate_chroot_blacklist, 501 ], 502 ) 503 max_builds = wtforms.IntegerField( 504 "Max number of builds", 505 description="""Keep only the specified number of the newest-by-id builds 506 (garbage collector is run daily)""", 507 render_kw={'placeholder': 'Optional - integer, e.g. 10, zero/empty disables'}, 508 validators=[ 509 wtforms.validators.Optional(), 510 wtforms.validators.NumberRange(min=0, max=100)], 511 default=None, 512 )513516 scm_type = wtforms.SelectField( 517 "Type", 518 choices=[("git", "Git"), ("svn", "SVN")], 519 default="git") 520 521 clone_url = wtforms.StringField( 522 "Clone url", 523 validators=[ 524 wtforms.validators.DataRequired(), 525 wtforms.validators.URL()]) 526 527 committish = wtforms.StringField( 528 "Committish", 529 validators=[ 530 wtforms.validators.Optional()]) 531 532 subdirectory = wtforms.StringField( 533 "Subdirectory", 534 validators=[ 535 wtforms.validators.Optional()]) 536 537 spec = wtforms.StringField( 538 "Spec File", 539 validators=[ 540 wtforms.validators.Optional(), 541 wtforms.validators.Regexp( 542 r"^.+\.spec$", 543 message="RPM spec file must end with .spec")]) 544 545 srpm_build_method = wtforms.SelectField( 546 "SRPM build method", 547 choices=[(x, x) for x in ["rpkg", "tito", "tito_test", "make_srpm"]], 548 default="rpkg") 549 550 @property560552 return json.dumps({ 553 "type": self.scm_type.data, 554 "clone_url": self.clone_url.data, 555 "subdirectory": self.subdirectory.data, 556 "committish": self.committish.data, 557 "spec": self.spec.data, 558 "srpm_build_method": self.srpm_build_method.data, 559 })563 pypi_package_name = wtforms.StringField( 564 "PyPI package name", 565 validators=[wtforms.validators.DataRequired()]) 566 567 pypi_package_version = wtforms.StringField( 568 "PyPI package version", 569 validators=[ 570 wtforms.validators.Optional(), 571 ]) 572 573 spec_template = wtforms.SelectField( 574 "Spec template", 575 choices=[ 576 ("", "default"), 577 ("fedora", "fedora"), 578 ("epel7", "epel7"), 579 ("mageia", "mageia"), 580 ("pld", "pld"), 581 ], default="") 582 583 python_versions = MultiCheckboxField( 584 'Build for Python', 585 choices=[ 586 ('3', 'python3'), 587 ('2', 'python2') 588 ], 589 default=['3', '2']) 590 591 @property599593 return json.dumps({ 594 "pypi_package_name": self.pypi_package_name.data, 595 "pypi_package_version": self.pypi_package_version.data, 596 "spec_template": self.spec_template.data, 597 "python_versions": self.python_versions.data 598 })602 gem_name = wtforms.StringField( 603 "Gem Name", 604 validators=[wtforms.validators.DataRequired()]) 605 606 @property611614 """ 615 @deprecated 616 """ 617 git_url = wtforms.StringField( 618 "Git URL", 619 validators=[ 620 wtforms.validators.DataRequired(), 621 wtforms.validators.URL()]) 622 623 git_directory = wtforms.StringField( 624 "Git Directory", 625 validators=[ 626 wtforms.validators.Optional()]) 627 628 git_branch = wtforms.StringField( 629 "Git Branch", 630 validators=[ 631 wtforms.validators.Optional()]) 632 633 tito_test = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 634 635 @property645637 return json.dumps({ 638 "type": 'git', 639 "clone_url": self.git_url.data, 640 "committish": self.git_branch.data, 641 "subdirectory": self.git_directory.data, 642 "spec": '', 643 "srpm_build_method": 'tito_test' if self.tito_test.data else 'tito', 644 })648 """ 649 @deprecated 650 """ 651 scm_type = wtforms.SelectField( 652 "SCM Type", 653 choices=[("git", "Git"), ("svn", "SVN")]) 654 655 scm_url = wtforms.StringField( 656 "SCM URL", 657 validators=[ 658 wtforms.validators.DataRequired(), 659 wtforms.validators.URL()]) 660 661 scm_branch = wtforms.StringField( 662 "Git Branch", 663 validators=[ 664 wtforms.validators.Optional()]) 665 666 scm_subdir = wtforms.StringField( 667 "Subdirectory", 668 validators=[ 669 wtforms.validators.Optional()]) 670 671 spec = wtforms.StringField( 672 "Spec File", 673 validators=[ 674 wtforms.validators.Optional(), 675 wtforms.validators.Regexp( 676 r"^.+\.spec$", 677 message="RPM spec file must end with .spec")]) 678 679 @property689692 """ 693 @deprecated 694 """ 695 clone_url = wtforms.StringField( 696 "Clone Url", 697 validators=[wtforms.validators.DataRequired()]) 698 699 branch = wtforms.StringField( 700 "Branch", 701 validators=[wtforms.validators.Optional()]) 702 703 @property713716 if not string: 717 return string 718 719 if string.split('\n')[0].endswith('\r'): 720 # This script is most probably coming from the web-UI, where 721 # web-browsers mistakenly put '\r\n' as EOL; and that would just 722 # mean that the script is not executable (any line can mean 723 # syntax error, but namely shebang would cause 100% fail) 724 string = string.replace('\r\n', '\n') 725 726 # And append newline to have a valid unix file. 727 if not string.endswith('\n'): 728 string += '\n' 729 730 return string731734 script = wtforms.TextAreaField( 735 "Script", 736 validators=[ 737 wtforms.validators.DataRequired(), 738 wtforms.validators.Length( 739 max=4096, 740 message="Maximum script size is 4kB"), 741 ], 742 filters=[cleanup_script], 743 ) 744 745 builddeps = wtforms.StringField( 746 "Build dependencies", 747 validators=[wtforms.validators.Optional()]) 748 749 chroot = wtforms.SelectField( 750 'Mock chroot', 751 choices=[], 752 default='fedora-latest-x86_64', 753 ) 754 755 resultdir = wtforms.StringField( 756 "Result directory", 757 validators=[wtforms.validators.Optional()]) 758786760 super(PackageFormCustom, self).__init__(*args, **kwargs) 761 chroot_objects = models.MockChroot.query.filter(models.MockChroot.is_active).all() 762 763 chroots = [c.name for c in chroot_objects] 764 chroots.sort() 765 chroots = [(name, name) for name in chroots] 766 767 arches = set() 768 for ch in chroot_objects: 769 if ch.os_release == 'fedora': 770 arches.add(ch.arch) 771 772 self.chroot.choices = [] 773 if arches: 774 self.chroot.choices += [('fedora-latest-' + l, 'fedora-latest-' + l) for l in arches] 775 776 self.chroot.choices += chroots777 778 @property797790 form_cls = BaseBuildFormFactory(active_chroots, FlaskForm) 791 form_cls.packages = MultiCheckboxField( 792 "Packages", 793 choices=[(name, name) for name in package_names], 794 default=package_names, 795 validators=[wtforms.validators.DataRequired()]) 796 return form_cls809 810 F.memory_reqs = wtforms.IntegerField( 811 "Memory requirements", 812 validators=[ 813 wtforms.validators.Optional(), 814 wtforms.validators.NumberRange( 815 min=constants.MIN_BUILD_MEMORY, 816 max=constants.MAX_BUILD_MEMORY)], 817 default=constants.DEFAULT_BUILD_MEMORY) 818 819 F.timeout = wtforms.IntegerField( 820 "Timeout", 821 validators=[ 822 wtforms.validators.Optional(), 823 wtforms.validators.NumberRange( 824 min=constants.MIN_BUILD_TIMEOUT, 825 max=constants.MAX_BUILD_TIMEOUT)], 826 default=constants.DEFAULT_BUILD_TIMEOUT) 827 828 F.enable_net = wtforms.BooleanField(false_values=FALSE_VALUES) 829 F.background = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 830 F.project_dirname = wtforms.StringField(default=None) 831 832 # overrides BasePackageForm.package_name and is unused for building 833 F.package_name = wtforms.StringField() 834 835 # fill chroots based on project settings 836 F.chroots_list = [x.name for x in active_chroots] 837 F.chroots_list.sort() 838 F.chroots_sets = {} 839 840 package_chroots = set(F.chroots_list) 841 if package: 842 package_chroots = set([ch.name for ch in package.chroots]) 843 844 for ch in F.chroots_list: 845 default = ch in package_chroots 846 setattr(F, ch, wtforms.BooleanField(ch, default=default, false_values=FALSE_VALUES)) 847 if ch[0] in F.chroots_sets: 848 F.chroots_sets[ch[0]].append(ch) 849 else: 850 F.chroots_sets[ch[0]] = [ch] 851 return F 852 857 865 873 878 883 888801 class F(form): 802 @property 803 def selected_chroots(self): 804 selected = [] 805 for ch in self.chroots_list: 806 if getattr(self, ch).data: 807 selected.append(ch) 808 return selected897 902892 form = BaseBuildFormFactory(active_chroots, FlaskForm) 893 form.pkgs = FileField('srpm', validators=[ 894 FileRequired(), 895 SrpmValidator()]) 896 return form915906 form = BaseBuildFormFactory(active_chroots, FlaskForm) 907 form.pkgs = wtforms.TextAreaField( 908 "Pkgs", 909 validators=[ 910 wtforms.validators.DataRequired(message="URLs to packages are required"), 911 UrlListValidator(), 912 UrlSrpmListValidator()], 913 filters=[StringListFilter()]) 914 return form918 modulemd = FileField("modulemd", validators=[ 919 FileRequired(), 920 # @TODO Validate modulemd.yaml file 921 ]) 922 923 create = wtforms.BooleanField("create", default=True, false_values=FALSE_VALUES) 924 build = wtforms.BooleanField("build", default=True, false_values=FALSE_VALUES)925928 modulemd = FileField("modulemd") 929 scmurl = wtforms.StringField() 930 branch = wtforms.StringField()931934 repo_url = wtforms.StringField("repo_url", default='') 935 api_key = wtforms.StringField("api_key", default='') 936943946 947 """ 948 Validator for editing chroots in project 949 (adding packages to minimal chroot) 950 """ 951 952 buildroot_pkgs = wtforms.StringField("Packages") 953 954 repos = wtforms.TextAreaField('Repos', 955 validators=[UrlRepoListValidator(), 956 wtforms.validators.Optional()], 957 filters=[StringListFilter()]) 958 959 comps = FileField("comps_xml") 960 961 with_opts = wtforms.StringField("With options") 962 without_opts = wtforms.StringField("Without options")963 968971 comment = wtforms.TextAreaField("Comment")972975 976 @staticmethod 980 981 builder_default = False 982 admin_default = False 983 984 if permission: 985 if permission.copr_builder != helpers.PermissionEnum("nothing"): 986 builder_default = True 987 if permission.copr_admin != helpers.PermissionEnum("nothing"): 988 admin_default = True 989 990 setattr(F, "copr_builder", 991 wtforms.BooleanField( 992 default=builder_default, 993 false_values=FALSE_VALUES, 994 filters=[ValueToPermissionNumberFilter()])) 995 996 setattr(F, "copr_admin", 997 wtforms.BooleanField( 998 default=admin_default, 999 false_values=FALSE_VALUES, 1000 filters=[ValueToPermissionNumberFilter()])) 1001 1002 return F10031006 1007 """Creates a dynamic form for given set of copr permissions""" 1008 @staticmethod 1012 1013 for perm in permissions: 1014 builder_choices = helpers.PermissionEnum.choices_list() 1015 admin_choices = helpers.PermissionEnum.choices_list() 1016 1017 builder_default = perm.copr_builder 1018 admin_default = perm.copr_admin 1019 1020 setattr(F, "copr_builder_{0}".format(perm.user.id), 1021 wtforms.SelectField( 1022 choices=builder_choices, 1023 default=builder_default, 1024 coerce=int)) 1025 1026 setattr(F, "copr_admin_{0}".format(perm.user.id), 1027 wtforms.SelectField( 1028 choices=admin_choices, 1029 default=admin_default, 1030 coerce=int)) 1031 1032 return F10331036 description = wtforms.TextAreaField('Description', 1037 validators=[wtforms.validators.Optional()]) 1038 1039 instructions = wtforms.TextAreaField('Instructions', 1040 validators=[wtforms.validators.Optional()]) 1041 1042 chroots = wtforms.TextAreaField('Chroots', 1043 validators=[wtforms.validators.Optional(), ChrootsValidator()]) 1044 1045 repos = wtforms.TextAreaField('Repos', 1046 validators=[UrlRepoListValidator(), 1047 wtforms.validators.Optional()], 1048 filters=[StringListFilter()]) 1049 1050 disable_createrepo = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1051 unlisted_on_hp = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1052 auto_prune = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1053 use_bootstrap_container = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1054 follow_fedora_branching = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1055 follow_fedora_branching = wtforms.BooleanField(default=True, false_values=FALSE_VALUES) 1056 delete_after_days = wtforms.IntegerField( 1057 validators=[wtforms.validators.Optional(), 1058 wtforms.validators.NumberRange(min=-1, max=60)], 1059 filters=[(lambda x : -1 if x is None else x)]) 1060 1061 # Deprecated, use `enable_net` instead 1062 build_enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1063 enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)10641067 @staticmethod10901069 class F(FlaskForm): 1070 source = wtforms.StringField( 1071 "Source", 1072 default=copr.full_name) 1073 1074 owner = wtforms.SelectField( 1075 "Fork owner", 1076 choices=[(user.name, user.name)] + [(g.at_name, g.at_name) for g in groups], 1077 default=user.name, 1078 validators=[wtforms.validators.DataRequired()]) 1079 1080 name = wtforms.StringField( 1081 "Fork name", 1082 default=copr.name, 1083 validators=[wtforms.validators.DataRequired(), NameCharactersValidator()]) 1084 1085 confirm = wtforms.BooleanField( 1086 "Confirm", 1087 false_values=FALSE_VALUES, 1088 default=False)1089 return F1093 buildroot_pkgs = wtforms.StringField('Additional packages to be always present in minimal buildroot') 1094 repos = wtforms.TextAreaField('Additional repos to be used for builds in chroot', 1095 validators=[UrlRepoListValidator(), 1096 wtforms.validators.Optional()], 1097 filters=[StringListFilter()]) 1098 comps = None 1099 upload_comps = FileField("Upload comps.xml") 1100 delete_comps = wtforms.BooleanField("Delete comps.xml", false_values=FALSE_VALUES)11011104 copr_ids = wtforms.SelectMultipleField(wtforms.IntegerField("Pinned Copr ID")) 11051121 11251107 if any([i and not i.isnumeric() for i in self.copr_ids.data]): 1108 self.errors["coprs"] = ["Unexpected value selected"] 1109 return False 1110 1111 limit = app.config["PINNED_PROJECTS_LIMIT"] 1112 if len(self.copr_ids.data) > limit: 1113 self.errors["coprs"] = ["Too many pinned projects. Limit is {}!".format(limit)] 1114 return False 1115 1116 if len(list(filter(None, self.copr_ids.data))) != len(set(filter(None, self.copr_ids.data))): 1117 self.errors["coprs"] = ["You can pin a particular project only once"] 1118 return False 1119 1120 return True1128 project = wtforms.StringField("Project")1129113211411134 if not message: 1135 message = "Group with the alias '{}' already exists." 1136 self.message = message11371139 if UsersLogic.group_alias_exists(field.data): 1140 raise wtforms.ValidationError(self.message.format(field.data))1144 1145 name = wtforms.StringField( 1146 validators=[ 1147 wtforms.validators.Regexp( 1148 re.compile(r"^[\w.-]+$"), 1149 message="Name must contain only letters," 1150 "digits, underscores, dashes and dots."), 1151 GroupUniqueNameValidator() 1152 ] 1153 )11541157 builds = wtforms.FieldList(wtforms.StringField("Builds ID list")) 1158 packages = wtforms.FieldList(wtforms.StringField("Packages list")) 1159 filter = wtforms.FieldList(wtforms.StringField("Package Filter")) 1160 api = wtforms.FieldList(wtforms.StringField("Module API")) 1161 profile_names = wtforms.FieldList(wtforms.StringField("Install Profiles"), min_entries=2) 1162 profile_pkgs = wtforms.FieldList(wtforms.FieldList(wtforms.StringField("Install Profiles")), min_entries=2) 1163 116711881169 if not FlaskForm.validate(self): 1170 return False 1171 1172 # Profile names should be unique 1173 names = [x for x in self.profile_names.data if x] 1174 if len(set(names)) < len(names): 1175 self.errors["profiles"] = ["Profile names must be unique"] 1176 return False 1177 1178 # WORKAROUND 1179 # profile_pkgs are somehow sorted so if I fill profile_name in the first box and 1180 # profile_pkgs in seconds box, it is sorted and validated correctly 1181 for i in range(0, len(self.profile_names.data)): 1182 # If profile name is not set, then there should not be any packages in this profile 1183 if not flask.request.form["profile_names-{}".format(i)]: 1184 if [j for j in range(0, len(self.profile_names)) if "profile_pkgs-{}-{}".format(i, j) in flask.request.form]: 1185 self.errors["profiles"] = ["Missing profile name"] 1186 return False 1187 return True1191 owner = wtforms.StringField("Owner Name", validators=[wtforms.validators.DataRequired()]) 1192 copr = wtforms.StringField("Copr Name", validators=[wtforms.validators.DataRequired()]) 1193 name = wtforms.StringField("Name", validators=[wtforms.validators.DataRequired()]) 1194 stream = wtforms.StringField("Stream", validators=[wtforms.validators.DataRequired()]) 1195 version = wtforms.IntegerField("Version", validators=[wtforms.validators.DataRequired()]) 1196 arch = wtforms.StringField("Arch", validators=[wtforms.validators.DataRequired()])1197
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 | http://epydoc.sourceforge.net |